From a401386f82af96fa40958d325f89dd7e64636fcc Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 29 Apr 2021 20:54:40 +0200 Subject: [PATCH] A key agreement algorithm can contain a key derivation PSA_ALG_KEY_AGREEMENT(..., kdf) is a valid key derivation algorithm when kdf is one. Signed-off-by: Gilles Peskine --- scripts/mbedtls_dev/crypto_knowledge.py | 20 ++++++++++++++++++++ tests/scripts/generate_psa_tests.py | 6 +++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/scripts/mbedtls_dev/crypto_knowledge.py b/scripts/mbedtls_dev/crypto_knowledge.py index adda02f52..73890f81a 100644 --- a/scripts/mbedtls_dev/crypto_knowledge.py +++ b/scripts/mbedtls_dev/crypto_knowledge.py @@ -366,3 +366,23 @@ class Algorithm: self.head = self.determine_head(self.base_expression) self.category = self.determine_category(self.base_expression, self.head) self.is_wildcard = self.determine_wildcard(self.expression) + + def is_key_agreement_with_derivation(self) -> bool: + """Whether this is a combined key agreement and key derivation algorithm.""" + if self.category != AlgorithmCategory.KEY_AGREEMENT: + return False + m = re.match(r'PSA_ALG_KEY_AGREEMENT\(\w+,\s*(.*)\)\Z', self.expression) + if not m: + return False + kdf_alg = m.group(1) + # Assume kdf_alg is either a valid KDF or 0. + return not re.match(r'(?:0[Xx])?0+\s*\Z', kdf_alg) + + def can_do(self, category: AlgorithmCategory) -> bool: + """Whether this algorithm fits the specified operation category.""" + if category == self.category: + return True + if category == AlgorithmCategory.KEY_DERIVATION and \ + self.is_key_agreement_with_derivation(): + return True + return False diff --git a/tests/scripts/generate_psa_tests.py b/tests/scripts/generate_psa_tests.py index 6c05b8937..81abce7bc 100755 --- a/tests/scripts/generate_psa_tests.py +++ b/tests/scripts/generate_psa_tests.py @@ -375,7 +375,7 @@ class OpFail: category: crypto_knowledge.AlgorithmCategory, ) -> Iterator[test_case.TestCase]: """Generate failure test cases for keyless operations with the specified algorithm.""" - if category == alg.category: + if alg.can_do(category): # Compatible operation, unsupported algorithm for dep in automatic_dependencies(alg.base_expression): yield self.make_test_case(alg, category, @@ -394,7 +394,7 @@ class OpFail: for kt in self.key_types: key_is_compatible = kt.can_do(alg) # To do: public key for a private key operation - if key_is_compatible and category == alg.category: + if key_is_compatible and alg.can_do(category): # Compatible key and operation, unsupported algorithm for dep in automatic_dependencies(alg.base_expression): yield self.make_test_case(alg, category, @@ -405,7 +405,7 @@ class OpFail: yield self.make_test_case(alg, category, self.Reason.INVALID, kt=kt) - elif category == alg.category: + elif alg.can_do(category): # Incompatible key, compatible operation, supported algorithm yield self.make_test_case(alg, category, self.Reason.INCOMPATIBLE,