Refactor usage flag formatting and implication

When generating storage format tests, pass usage flags around as a list, and
format them as the last thing.

In Storagekey(), simplify the addition of implicit usage flags: this no
longer requires parsing.

The output is unchanged.

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This commit is contained in:
Gilles Peskine 2022-03-17 22:32:59 +01:00
parent 6213a00ec1
commit d9af978f41

View file

@ -454,7 +454,7 @@ class StorageKey(psa_storage.Key):
def __init__( def __init__(
self, self,
usage: str, usage: Iterable[str],
without_implicit_usage: Optional[bool] = False, without_implicit_usage: Optional[bool] = False,
**kwargs **kwargs
) -> None: ) -> None:
@ -463,13 +463,16 @@ class StorageKey(psa_storage.Key):
* `usage` : The usage flags used for the key. * `usage` : The usage flags used for the key.
* `without_implicit_usage`: Flag to defide to apply the usage extension * `without_implicit_usage`: Flag to defide to apply the usage extension
""" """
super().__init__(usage=usage, **kwargs) usage_flags = set(usage)
if not without_implicit_usage: if not without_implicit_usage:
for flag, implicit in self.IMPLICIT_USAGE_FLAGS.items(): for flag in sorted(usage_flags):
if self.usage.value() & psa_storage.Expr(flag).value() and \ if flag in self.IMPLICIT_USAGE_FLAGS:
self.usage.value() & psa_storage.Expr(implicit).value() == 0: usage_flags.add(self.IMPLICIT_USAGE_FLAGS[flag])
self.usage = psa_storage.Expr(self.usage.string + ' | ' + implicit) if usage_flags:
usage_expression = ' | '.join(sorted(usage_flags))
else:
usage_expression = '0'
super().__init__(usage=usage_expression, **kwargs)
class StorageTestData(StorageKey): class StorageTestData(StorageKey):
"""Representation of test case data for storage format testing.""" """Representation of test case data for storage format testing."""
@ -477,7 +480,7 @@ class StorageTestData(StorageKey):
def __init__( def __init__(
self, self,
description: str, description: str,
expected_usage: Optional[str] = None, expected_usage: Optional[List[str]] = None,
**kwargs **kwargs
) -> None: ) -> None:
"""Prepare to generate test data """Prepare to generate test data
@ -489,7 +492,12 @@ class StorageTestData(StorageKey):
""" """
super().__init__(**kwargs) super().__init__(**kwargs)
self.description = description #type: str self.description = description #type: str
self.expected_usage = expected_usage if expected_usage else self.usage.string #type: str if expected_usage is None:
self.expected_usage = self.usage #type: psa_storage.Expr
elif expected_usage:
self.expected_usage = psa_storage.Expr(' | '.join(expected_usage))
else:
self.expected_usage = psa_storage.Expr(0)
class StorageFormat: class StorageFormat:
"""Storage format stability test cases.""" """Storage format stability test cases."""
@ -522,7 +530,7 @@ class StorageFormat:
tc.set_description('PSA storage {}: {}'.format(verb, key.description)) tc.set_description('PSA storage {}: {}'.format(verb, key.description))
dependencies = automatic_dependencies( dependencies = automatic_dependencies(
key.lifetime.string, key.type.string, key.lifetime.string, key.type.string,
key.expected_usage, key.alg.string, key.alg2.string, key.alg.string, key.alg2.string,
) )
dependencies = finish_family_dependencies(dependencies, key.bits) dependencies = finish_family_dependencies(dependencies, key.bits)
tc.set_dependencies(dependencies) tc.set_dependencies(dependencies)
@ -543,7 +551,8 @@ class StorageFormat:
extra_arguments = [' | '.join(flags) if flags else '0'] extra_arguments = [' | '.join(flags) if flags else '0']
tc.set_arguments([key.lifetime.string, tc.set_arguments([key.lifetime.string,
key.type.string, str(key.bits), key.type.string, str(key.bits),
key.expected_usage, key.alg.string, key.alg2.string, key.expected_usage.string,
key.alg.string, key.alg2.string,
'"' + key.material.hex() + '"', '"' + key.material.hex() + '"',
'"' + key.hex() + '"', '"' + key.hex() + '"',
*extra_arguments]) *extra_arguments])
@ -562,7 +571,7 @@ class StorageFormat:
key = StorageTestData(version=self.version, key = StorageTestData(version=self.version,
id=1, lifetime=lifetime, id=1, lifetime=lifetime,
type='PSA_KEY_TYPE_RAW_DATA', bits=8, type='PSA_KEY_TYPE_RAW_DATA', bits=8,
usage='PSA_KEY_USAGE_EXPORT', alg=0, alg2=0, usage=['PSA_KEY_USAGE_EXPORT'], alg=0, alg2=0,
material=b'L', material=b'L',
description=description) description=description)
return key return key
@ -588,19 +597,21 @@ class StorageFormat:
test_implicit_usage: Optional[bool] = True test_implicit_usage: Optional[bool] = True
) -> StorageTestData: ) -> StorageTestData:
"""Construct a test key for the given key usage.""" """Construct a test key for the given key usage."""
usage = ' | '.join(usage_flags) if usage_flags else '0'
if short is None:
short = re.sub(r'\bPSA_KEY_USAGE_', r'', usage)
extra_desc = ' without implication' if test_implicit_usage else '' extra_desc = ' without implication' if test_implicit_usage else ''
description = 'usage' + extra_desc + ': ' + short description = 'usage' + extra_desc + ': '
key1 = StorageTestData(version=self.version, key1 = StorageTestData(version=self.version,
id=1, lifetime=0x00000001, id=1, lifetime=0x00000001,
type='PSA_KEY_TYPE_RAW_DATA', bits=8, type='PSA_KEY_TYPE_RAW_DATA', bits=8,
expected_usage=usage, expected_usage=usage_flags,
without_implicit_usage=not test_implicit_usage, without_implicit_usage=not test_implicit_usage,
usage=usage, alg=0, alg2=0, usage=usage_flags, alg=0, alg2=0,
material=b'K', material=b'K',
description=description) description=description)
if short is None:
key1.description += re.sub(r'\bPSA_KEY_USAGE_', r'',
key1.expected_usage.string)
else:
key1.description += short
return key1 return key1
def generate_keys_for_usage_flags(self, **kwargs) -> Iterator[StorageTestData]: def generate_keys_for_usage_flags(self, **kwargs) -> Iterator[StorageTestData]:
@ -631,7 +642,7 @@ class StorageFormat:
If alg is not None, this key allows it. If alg is not None, this key allows it.
""" """
usage_flags = 'PSA_KEY_USAGE_EXPORT' usage_flags = ['PSA_KEY_USAGE_EXPORT']
alg1 = 0 if alg is None else alg.expression #type: psa_storage.Exprable alg1 = 0 if alg is None else alg.expression #type: psa_storage.Exprable
alg2 = 0 alg2 = 0
key_material = kt.key_material(bits) key_material = kt.key_material(bits)
@ -685,7 +696,7 @@ class StorageFormat:
# compatible key. # compatible key.
descr = re.sub(r'PSA_ALG_', r'', alg) descr = re.sub(r'PSA_ALG_', r'', alg)
descr = re.sub(r',', r', ', re.sub(r' +', r'', descr)) descr = re.sub(r',', r', ', re.sub(r' +', r'', descr))
usage = 'PSA_KEY_USAGE_EXPORT' usage = ['PSA_KEY_USAGE_EXPORT']
key1 = StorageTestData(version=self.version, key1 = StorageTestData(version=self.version,
id=1, lifetime=0x00000001, id=1, lifetime=0x00000001,
type='PSA_KEY_TYPE_RAW_DATA', bits=8, type='PSA_KEY_TYPE_RAW_DATA', bits=8,
@ -758,9 +769,9 @@ class StorageFormatV0(StorageFormat):
""" """
bits = key_type.sizes_to_test()[0] bits = key_type.sizes_to_test()[0]
implicit_usage = StorageKey.IMPLICIT_USAGE_FLAGS[implyer_usage] implicit_usage = StorageKey.IMPLICIT_USAGE_FLAGS[implyer_usage]
usage_flags = 'PSA_KEY_USAGE_EXPORT' usage_flags = ['PSA_KEY_USAGE_EXPORT']
material_usage_flags = usage_flags + ' | ' + implyer_usage material_usage_flags = usage_flags + [implyer_usage]
expected_usage_flags = material_usage_flags + ' | ' + implicit_usage expected_usage_flags = material_usage_flags + [implicit_usage]
alg2 = 0 alg2 = 0
key_material = key_type.key_material(bits) key_material = key_type.key_material(bits)
usage_expression = re.sub(r'PSA_KEY_USAGE_', r'', implyer_usage) usage_expression = re.sub(r'PSA_KEY_USAGE_', r'', implyer_usage)