Expand psa_generate_tests to support constructor arguments

In macro_collector.py, base InputsForTest on PSAMacroEnumerator rather
than PSAMacroCollector. It didn't make much sense to use
PSAMacroCollector anymore since InputsForTest didn't use anything
other than the constructor.

psa_generate_tests now generates arguments for more macros.
In particular, it now collects macro arguments from
test_suite_psa_crypto_metadata. Algorithms with parameters are now
supported.

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This commit is contained in:
Gilles Peskine 2021-04-19 13:50:25 +02:00
parent ae9f14b159
commit b93f854f4c
4 changed files with 2835 additions and 146 deletions

View File

@ -105,6 +105,16 @@ class PSAMacroEnumerator:
'tag_length': [],
'min_tag_length': [],
} #type: Dict[str, List[str]]
self.include_intermediate = False
def is_internal_name(self, name: str) -> bool:
"""Whether this is an internal macro. Internal macros will be skipped."""
if not self.include_intermediate:
if name.endswith('_BASE') or name.endswith('_NONE'):
return True
if '_CATEGORY_' in name:
return True
return name.endswith('_FLAG') or name.endswith('_MASK')
def gather_arguments(self) -> None:
"""Populate the list of values for macro arguments.
@ -192,15 +202,6 @@ class PSAMacroCollector(PSAMacroEnumerator):
self.key_types_from_group = {} #type: Dict[str, str]
self.algorithms_from_hash = {} #type: Dict[str, str]
def is_internal_name(self, name: str) -> bool:
"""Whether this is an internal macro. Internal macros will be skipped."""
if not self.include_intermediate:
if name.endswith('_BASE') or name.endswith('_NONE'):
return True
if '_CATEGORY_' in name:
return True
return name.endswith('_FLAG') or name.endswith('_MASK')
def record_algorithm_subtype(self, name: str, expansion: str) -> None:
"""Record the subtype of an algorithm constructor.
@ -301,7 +302,7 @@ class PSAMacroCollector(PSAMacroEnumerator):
self.read_line(line)
class InputsForTest(PSAMacroCollector):
class InputsForTest(PSAMacroEnumerator):
# pylint: disable=too-many-instance-attributes
"""Accumulate information about macros to test.
enumerate
@ -408,7 +409,8 @@ enumerate
name = m.group(1)
self.all_declared.add(name)
if re.search(self._excluded_name_re, name) or \
name in self._excluded_names:
name in self._excluded_names or \
self.is_internal_name(name):
return
dest = self.table_by_prefix.get(m.group(2))
if dest is None:

View File

@ -94,23 +94,25 @@ class Information:
@staticmethod
def remove_unwanted_macros(
constructors: macro_collector.PSAMacroCollector
constructors: macro_collector.PSAMacroEnumerator
) -> None:
# Mbed TLS doesn't support DSA. Don't attempt to generate any related
# test case.
# Mbed TLS doesn't support finite-field DH yet and will not support
# finite-field DSA. Don't attempt to generate any related test case.
constructors.key_types.discard('PSA_KEY_TYPE_DH_KEY_PAIR')
constructors.key_types.discard('PSA_KEY_TYPE_DH_PUBLIC_KEY')
constructors.key_types.discard('PSA_KEY_TYPE_DSA_KEY_PAIR')
constructors.key_types.discard('PSA_KEY_TYPE_DSA_PUBLIC_KEY')
constructors.algorithms_from_hash.pop('PSA_ALG_DSA', None)
constructors.algorithms_from_hash.pop('PSA_ALG_DETERMINISTIC_DSA', None)
def read_psa_interface(self) -> macro_collector.PSAMacroCollector:
def read_psa_interface(self) -> macro_collector.PSAMacroEnumerator:
"""Return the list of known key types, algorithms, etc."""
constructors = macro_collector.InputsForTest()
header_file_names = ['include/psa/crypto_values.h',
'include/psa/crypto_extra.h']
test_suites = ['tests/suites/test_suite_psa_crypto_metadata.data']
for header_file_name in header_file_names:
with open(header_file_name, 'rb') as header_file:
constructors.read_file(header_file)
constructors.parse_header(header_file_name)
for test_cases in test_suites:
constructors.parse_test_cases(test_cases)
self.remove_unwanted_macros(constructors)
constructors.gather_arguments()
return constructors
@ -194,14 +196,18 @@ class NotSupported:
)
# To be added: derive
ECC_KEY_TYPES = ('PSA_KEY_TYPE_ECC_KEY_PAIR',
'PSA_KEY_TYPE_ECC_PUBLIC_KEY')
def test_cases_for_not_supported(self) -> Iterator[test_case.TestCase]:
"""Generate test cases that exercise the creation of keys of unsupported types."""
for key_type in sorted(self.constructors.key_types):
if key_type in self.ECC_KEY_TYPES:
continue
kt = crypto_knowledge.KeyType(key_type)
yield from self.test_cases_for_key_type_not_supported(kt)
for curve_family in sorted(self.constructors.ecc_curves):
for constr in ('PSA_KEY_TYPE_ECC_KEY_PAIR',
'PSA_KEY_TYPE_ECC_PUBLIC_KEY'):
for constr in self.ECC_KEY_TYPES:
kt = crypto_knowledge.KeyType(constr, [curve_family])
yield from self.test_cases_for_key_type_not_supported(
kt, param_descr='type')
@ -330,16 +336,9 @@ class StorageFormat:
def all_keys_for_types(self) -> Iterator[StorageKey]:
"""Generate test keys covering key types and their representations."""
for key_type in sorted(self.constructors.key_types):
key_types = sorted(self.constructors.key_types)
for key_type in self.constructors.generate_expressions(key_types):
yield from self.keys_for_type(key_type)
for key_type in sorted(self.constructors.key_types_from_curve):
for curve in sorted(self.constructors.ecc_curves):
yield from self.keys_for_type(key_type, [curve])
## Diffie-Hellman (FFDH) is not supported yet, either in
## crypto_knowledge.py or in Mbed TLS.
# for key_type in sorted(self.constructors.key_types_from_group):
# for group in sorted(self.constructors.dh_groups):
# yield from self.keys_for_type(key_type, [group])
def keys_for_algorithm(self, alg: str) -> Iterator[StorageKey]:
"""Generate test keys for the specified algorithm."""
@ -365,9 +364,9 @@ class StorageFormat:
def all_keys_for_algorithms(self) -> Iterator[StorageKey]:
"""Generate test keys covering algorithm encodings."""
for alg in sorted(self.constructors.algorithms):
algorithms = sorted(self.constructors.algorithms)
for alg in self.constructors.generate_expressions(algorithms):
yield from self.keys_for_algorithm(alg)
# To do: algorithm constructors with parameters
def all_test_cases(self) -> Iterator[test_case.TestCase]:
"""Generate all storage format test cases."""

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff