From 78e4c8a73ba7373d6c693015dffdc283b3c7391d Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 16 Dec 2024 20:25:07 +0100 Subject: [PATCH] PSA test case generation: operation fail: simplify NOT_SUPPORTED In `generate_psa_tests.py, `OpFail.make_test_case()` is only ever used with a single mechanism being not supported. Take advantage of that to simplify parts of the function. Call `psa_test_case.TestCase.assumes_not_supported()` instead of partly reinventing that wheel. No change to the generated output. Signed-off-by: Gilles Peskine --- scripts/generate_psa_tests.py | 27 +++++++++++----------- scripts/mbedtls_framework/psa_test_case.py | 6 +++++ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/scripts/generate_psa_tests.py b/scripts/generate_psa_tests.py index 4e165cbf0..3771859ea 100755 --- a/scripts/generate_psa_tests.py +++ b/scripts/generate_psa_tests.py @@ -11,7 +11,7 @@ generate only the specified files. import enum import re import sys -from typing import Callable, Dict, FrozenSet, Iterable, Iterator, List, Optional +from typing import Callable, Dict, Iterable, Iterator, List, Optional from mbedtls_framework import crypto_data_tests from mbedtls_framework import crypto_knowledge @@ -223,16 +223,19 @@ class OpFail: category: crypto_knowledge.AlgorithmCategory, reason: 'Reason', kt: Optional[crypto_knowledge.KeyType] = None, - not_deps: FrozenSet[str] = frozenset(), + not_supported: Optional[str] = None, ) -> test_case.TestCase: - """Construct a failure test case for a one-key or keyless operation.""" + """Construct a failure test case for a one-key or keyless operation. + + If `reason` is `Reason.NOT_SUPPORTED`, pass the not-supported + dependency symbol as the `not_supported` argument. + """ #pylint: disable=too-many-arguments,too-many-locals tc = psa_test_case.TestCase() pretty_alg = alg.short_expression() if reason == self.Reason.NOT_SUPPORTED: - short_deps = [re.sub(r'PSA_WANT_ALG_', r'', dep) - for dep in not_deps] - pretty_reason = '!' + '&'.join(sorted(short_deps)) + assert not_supported is not None + pretty_reason = '!' + re.sub(r'PSA_WANT_[A-Z]+_', r'', not_supported) else: pretty_reason = reason.name.lower() if kt: @@ -261,12 +264,8 @@ class OpFail: 'INVALID_ARGUMENT') arguments.append('PSA_ERROR_' + error) if reason == self.Reason.NOT_SUPPORTED: - # It isn't nice that we access the field directly. We should - # call tc.assumes_not_supported() instead, but that requires - # further refactoring here because that method assumes a - # mechanism symbol (e.g. PSA_KEY_TYPE_xxx), not a dependency - # symbol (e.g. PSA_WANT_KEY_TYPE_xxx) like we have here. - tc.negated_dependencies.update(not_deps) + assert not_supported is not None + tc.assumes_not_supported(not_supported) tc.set_arguments(arguments) return tc @@ -281,7 +280,7 @@ class OpFail: for dep in psa_information.automatic_dependencies(alg.base_expression): yield self.make_test_case(alg, category, self.Reason.NOT_SUPPORTED, - not_deps=frozenset([dep])) + not_supported=dep) else: # Incompatible operation, supported algorithm yield self.make_test_case(alg, category, self.Reason.INVALID) @@ -299,7 +298,7 @@ class OpFail: for dep in psa_information.automatic_dependencies(alg.base_expression): yield self.make_test_case(alg, category, self.Reason.NOT_SUPPORTED, - kt=kt, not_deps=frozenset([dep])) + kt=kt, not_supported=dep) # Public key for a private-key operation if category.is_asymmetric() and kt.is_public(): yield self.make_test_case(alg, category, diff --git a/scripts/mbedtls_framework/psa_test_case.py b/scripts/mbedtls_framework/psa_test_case.py index 7084bada8..77ba31b39 100644 --- a/scripts/mbedtls_framework/psa_test_case.py +++ b/scripts/mbedtls_framework/psa_test_case.py @@ -118,6 +118,9 @@ class TestCase(test_case.TestCase): def assumes_not_supported(self, name: str) -> None: """Negate the given mechanism for automatic dependency generation. + `name` can be either a dependency symbol (``PSA_WANT_xxx``) or + a mechanism name (``PSA_KEY_TYPE_xxx``, etc.). + Call this function before set_arguments() for a test case that should run if the given mechanism is not supported. @@ -129,6 +132,9 @@ class TestCase(test_case.TestCase): the key bit-size, this class assumes that only one bit-size is involved in a given test case. """ + if name.startswith('PSA_WANT_'): + self.negated_dependencies.add(name) + return if name == 'PSA_KEY_TYPE_RSA_KEY_PAIR' and \ self.key_bits is not None and \ self.key_pair_usage == ['GENERATE']: