Fix edge case with half-supported ECDSA
ECDSA has two variants: deterministic (PSA_ALG_DETERMINISTIC_ECDSA) and
randomized (PSA_ALG_ECDSA). The two variants are different for signature but
identical for verification. Mbed TLS accepts either variant as the algorithm
parameter for verification even when only the other variant is supported,
so we need to handle this as a special case when generating not-supported
test cases.
In this commit:
* Automatically generated not-supported test cases for ECDSA now require
both variants to be disabled.
* Add manually written not-supported test cases for the signature
operation when exactly one variant is supported.
* Add manually written positive test cases for the verification
operation when exactly one variant is supported.
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
diff --git a/tests/scripts/generate_psa_tests.py b/tests/scripts/generate_psa_tests.py
index 85b35e5..5cceb96 100755
--- a/tests/scripts/generate_psa_tests.py
+++ b/tests/scripts/generate_psa_tests.py
@@ -236,7 +236,8 @@
tc.set_key_bits(bits)
arguments.append(alg.expression)
if category.is_asymmetric():
- arguments.append('1' if reason == self.Reason.PUBLIC else '0')
+ private_only = (reason == self.Reason.PUBLIC)
+ arguments.append('1' if private_only else '0')
error = ('NOT_SUPPORTED' if reason == self.Reason.NOT_SUPPORTED else
'INVALID_ARGUMENT')
arguments.append('PSA_ERROR_' + error)
@@ -272,9 +273,25 @@
if key_is_compatible and alg.can_do(category):
# Compatible key and operation, unsupported algorithm
for dep in psa_information.automatic_dependencies(alg.base_expression):
+ deps = [dep]
+ # Special case: if one of deterministic/randomized
+ # ECDSA is supported but not the other, then the one
+ # that is not supported in the signature direction is
+ # still supported in the verification direction,
+ # because the two verification algorithms are
+ # identical. This property is how Mbed TLS chooses to
+ # behave, the specification would also allow it to
+ # reject the algorithm. In the generated test cases,
+ # we avoid this difficulty by not running the
+ # not-supported test case when exactly one of the
+ # two variants is supported.
+ if dep == 'PSA_WANT_ALG_DETERMINISTIC_ECDSA':
+ deps.append('PSA_WANT_ALG_ECDSA')
+ elif dep == 'PSA_WANT_ALG_ECDSA':
+ deps.append('PSA_WANT_ALG_DETERMINISTIC_ECDSA')
yield self.make_test_case(alg, category,
self.Reason.NOT_SUPPORTED,
- kt=kt, not_deps=frozenset([dep]))
+ kt=kt, not_deps=frozenset(deps))
# Public key for a private-key operation
if category.is_asymmetric() and kt.is_public():
yield self.make_test_case(alg, category,