Add key usage policy extension support for key generation

Signed-off-by: gabor-mezei-arm <gabor.mezei@arm.com>
This commit is contained in:
gabor-mezei-arm 2021-06-24 10:04:38 +02:00
parent a4102cb57d
commit 7748b6f24b
2 changed files with 42 additions and 7 deletions

View file

@ -101,6 +101,12 @@ class Key:
LATEST_VERSION = 0 LATEST_VERSION = 0
"""The latest version of the storage format.""" """The latest version of the storage format."""
EXTENDABLE_USAGE_FLAGS = {
Expr('PSA_KEY_USAGE_SIGN_HASH'): Expr('PSA_KEY_USAGE_SIGN_MESSAGE'),
Expr('PSA_KEY_USAGE_VERIFY_HASH'): Expr('PSA_KEY_USAGE_VERIFY_MESSAGE')
} #type: Dict[Expr, Expr]
"""The extendable usage flags with the corresponding extension flags."""
def __init__(self, *, def __init__(self, *,
version: Optional[int] = None, version: Optional[int] = None,
id: Optional[int] = None, #pylint: disable=redefined-builtin id: Optional[int] = None, #pylint: disable=redefined-builtin
@ -108,18 +114,27 @@ class Key:
type: Exprable, #pylint: disable=redefined-builtin type: Exprable, #pylint: disable=redefined-builtin
bits: int, bits: int,
usage: Exprable, alg: Exprable, alg2: Exprable, usage: Exprable, alg: Exprable, alg2: Exprable,
material: bytes #pylint: disable=used-before-assignment material: bytes, #pylint: disable=used-before-assignment
usage_extension: bool = True
) -> None: ) -> None:
self.version = self.LATEST_VERSION if version is None else version self.version = self.LATEST_VERSION if version is None else version
self.id = id #pylint: disable=invalid-name #type: Optional[int] self.id = id #pylint: disable=invalid-name #type: Optional[int]
self.lifetime = as_expr(lifetime) #type: Expr self.lifetime = as_expr(lifetime) #type: Expr
self.type = as_expr(type) #type: Expr self.type = as_expr(type) #type: Expr
self.bits = bits #type: int self.bits = bits #type: int
self.usage = as_expr(usage) #type: Expr self.original_usage = as_expr(usage) #type: Expr
self.updated_usage = self.original_usage #type: Expr
self.alg = as_expr(alg) #type: Expr self.alg = as_expr(alg) #type: Expr
self.alg2 = as_expr(alg2) #type: Expr self.alg2 = as_expr(alg2) #type: Expr
self.material = material #type: bytes self.material = material #type: bytes
if usage_extension:
for flag, extension in self.EXTENDABLE_USAGE_FLAGS.items():
if self.original_usage.value() & flag.value() and \
self.original_usage.value() & extension.value() == 0:
self.updated_usage = Expr(self.updated_usage.string +
' | ' + extension.string)
MAGIC = b'PSA\000KEY\000' MAGIC = b'PSA\000KEY\000'
@staticmethod @staticmethod
@ -151,7 +166,7 @@ class Key:
if self.version == 0: if self.version == 0:
attributes = self.pack('LHHLLL', attributes = self.pack('LHHLLL',
self.lifetime, self.type, self.bits, self.lifetime, self.type, self.bits,
self.usage, self.alg, self.alg2) self.updated_usage, self.alg, self.alg2)
material = self.pack('L', len(self.material)) + self.material material = self.pack('L', len(self.material)) + self.material
else: else:
raise NotImplementedError raise NotImplementedError

28
tests/scripts/generate_psa_tests.py Normal file → Executable file
View file

@ -236,12 +236,14 @@ class StorageKey(psa_storage.Key):
def __init__(self, *, description: str, **kwargs) -> None: def __init__(self, *, description: str, **kwargs) -> None:
super().__init__(**kwargs) super().__init__(**kwargs)
self.description = description #type: str self.description = description #type: str
self.usage = self.original_usage #type: psa_storage.Expr
class StorageKeyBuilder: class StorageKeyBuilder:
def __init__(self) -> None: def __init__(self, usage_extension: bool) -> None:
pass self.usage_extension = usage_extension #type: bool
def build(self, **kwargs) -> StorageKey: def build(self, **kwargs) -> StorageKey:
return StorageKey(**kwargs) return StorageKey(usage_extension = self.usage_extension, **kwargs)
class StorageFormat: class StorageFormat:
"""Storage format stability test cases.""" """Storage format stability test cases."""
@ -259,7 +261,7 @@ class StorageFormat:
self.constructors = info.constructors #type: macro_collector.PSAMacroEnumerator self.constructors = info.constructors #type: macro_collector.PSAMacroEnumerator
self.version = version #type: int self.version = version #type: int
self.forward = forward #type: bool self.forward = forward #type: bool
self.key_builder = StorageKeyBuilder() #type: StorageKeyBuilder self.key_builder = StorageKeyBuilder(usage_extension = True) #type: StorageKeyBuilder
def make_test_case(self, key: StorageKey) -> test_case.TestCase: def make_test_case(self, key: StorageKey) -> test_case.TestCase:
"""Construct a storage format test case for the given key. """Construct a storage format test case for the given key.
@ -473,6 +475,24 @@ class StorageFormatV0(StorageFormat):
def __init__(self, info: Information) -> None: def __init__(self, info: Information) -> None:
super().__init__(info, 0, False) super().__init__(info, 0, False)
def all_keys_for_usage_flags(self) -> List[StorageKey]:
"""Generate test keys covering usage flags."""
# First generate keys without usage policy extension for
# compatibility testing, then generate the keys with extension
# to check the extension is working.
keys = [] #type: List[StorageKey]
prev_builder = self.key_builder
self.key_builder = StorageKeyBuilder(usage_extension = False)
keys += super().all_keys_for_usage_flags(extra_desc = 'without extension')
self.key_builder = StorageKeyBuilder(usage_extension = True)
keys += super().all_keys_for_usage_flags(extra_desc = 'with extension')
self.key_builder = prev_builder
return keys
class TestGenerator: class TestGenerator:
"""Generate test data.""" """Generate test data."""