1111import enum
1212import re
1313import sys
14- from typing import Callable , Dict , FrozenSet , Iterable , Iterator , List , Optional
14+ from typing import Callable , Dict , Iterable , Iterator , List , Optional
1515
1616from mbedtls_framework import crypto_data_tests
1717from mbedtls_framework import crypto_knowledge
2626
2727def test_case_for_key_type_not_supported (
2828 verb : str , key_type : str , bits : int ,
29- dependencies : List [ str ] ,
29+ not_supported_mechanism : str ,
3030 * args : str ,
3131 param_descr : str = ''
3232) -> test_case .TestCase :
@@ -35,17 +35,16 @@ def test_case_for_key_type_not_supported(
3535 """
3636 tc = psa_test_case .TestCase ()
3737 short_key_type = crypto_knowledge .short_expression (key_type )
38- adverb = 'not' if dependencies else 'never '
39- if param_descr :
40- adverb = param_descr + ' ' + adverb
41- tc .set_description ( 'PSA {} {} {} -bit {} supported'
42- . format ( verb , short_key_type , bits , adverb ) )
38+ tc . set_description ( 'PSA {} {} {}-bit{} not supported '
39+ . format ( verb , short_key_type , bits ,
40+ ' ' + param_descr if param_descr else '' ))
41+ # if tc.description == 'PSA import RSA_KEY_PAIR 1024 -bit not supported':
42+ # import pdb; pdb.set_trace( )
4343 tc .set_function (verb + '_not_supported' )
4444 tc .set_key_bits (bits )
45- tc .set_key_pair_usage (verb .upper ())
45+ tc .set_key_pair_usage ([verb .upper ()])
46+ tc .assumes_not_supported (not_supported_mechanism )
4647 tc .set_arguments ([key_type ] + list (args ))
47- tc .set_dependencies (dependencies )
48- tc .skip_if_any_not_implemented (dependencies )
4948 return tc
5049
5150class KeyTypeNotSupported :
@@ -77,37 +76,27 @@ def test_cases_for_key_type_not_supported(
7776 # Don't generate test cases for key types that are always supported.
7877 # They would be skipped in all configurations, which is noise.
7978 return
80- import_dependencies = [('!' if param is None else '' ) +
81- psa_information .psa_want_symbol (kt .name )]
82- if kt .params is not None :
83- import_dependencies += [('!' if param == i else '' ) +
84- psa_information .psa_want_symbol (sym )
85- for i , sym in enumerate (kt .params )]
86- if kt .name .endswith ('_PUBLIC_KEY' ):
87- generate_dependencies = []
79+ if param is None :
80+ not_supported_mechanism = kt .name
8881 else :
89- generate_dependencies = \
90- psa_information .fix_key_pair_dependencies (import_dependencies , 'GENERATE' )
91- import_dependencies = \
92- psa_information .fix_key_pair_dependencies (import_dependencies , 'BASIC' )
82+ assert kt .params is not None
83+ not_supported_mechanism = kt .params [param ]
9384 for bits in kt .sizes_to_test ():
9485 yield test_case_for_key_type_not_supported (
9586 'import' , kt .expression , bits ,
96- psa_information . finish_family_dependencies ( import_dependencies , bits ) ,
87+ not_supported_mechanism ,
9788 test_case .hex_string (kt .key_material (bits )),
9889 param_descr = param_descr ,
9990 )
100- if not generate_dependencies and param is not None :
101- # If generation is impossible for this key type, rather than
102- # supported or not depending on implementation capabilities,
103- # only generate the test case once.
104- continue
105- # For public key we expect that key generation fails with
106- # INVALID_ARGUMENT. It is handled by KeyGenerate class.
91+ # Don't generate not-supported test cases for key generation of
92+ # public keys. Our implementation always returns
93+ # PSA_ERROR_INVALID_ARGUMENT when attempting to generate a
94+ # public key, so we cover this together with the positive cases
95+ # in the KeyGenerate class.
10796 if not kt .is_public ():
10897 yield test_case_for_key_type_not_supported (
10998 'generate' , kt .expression , bits ,
110- psa_information . finish_family_dependencies ( generate_dependencies , bits ) ,
99+ not_supported_mechanism ,
111100 str (bits ),
112101 param_descr = param_descr ,
113102 )
@@ -155,7 +144,7 @@ def test_case_for_key_generation(
155144 .format (short_key_type , bits ))
156145 tc .set_function ('generate_key' )
157146 tc .set_key_bits (bits )
158- tc .set_key_pair_usage ('GENERATE' )
147+ tc .set_key_pair_usage ([ 'GENERATE' ] )
159148 tc .set_arguments ([key_type ] + list (args ) + [result ])
160149 return tc
161150
@@ -234,16 +223,19 @@ def make_test_case(
234223 category : crypto_knowledge .AlgorithmCategory ,
235224 reason : 'Reason' ,
236225 kt : Optional [crypto_knowledge .KeyType ] = None ,
237- not_deps : FrozenSet [str ] = frozenset () ,
226+ not_supported : Optional [str ] = None ,
238227 ) -> test_case .TestCase :
239- """Construct a failure test case for a one-key or keyless operation."""
228+ """Construct a failure test case for a one-key or keyless operation.
229+
230+ If `reason` is `Reason.NOT_SUPPORTED`, pass the not-supported
231+ dependency symbol as the `not_supported` argument.
232+ """
240233 #pylint: disable=too-many-arguments,too-many-locals
241234 tc = psa_test_case .TestCase ()
242235 pretty_alg = alg .short_expression ()
243236 if reason == self .Reason .NOT_SUPPORTED :
244- short_deps = [re .sub (r'PSA_WANT_ALG_' , r'' , dep )
245- for dep in not_deps ]
246- pretty_reason = '!' + '&' .join (sorted (short_deps ))
237+ assert not_supported is not None
238+ pretty_reason = '!' + re .sub (r'PSA_WANT_[A-Z]+_' , r'' , not_supported )
247239 else :
248240 pretty_reason = reason .name .lower ()
249241 if kt :
@@ -257,16 +249,12 @@ def make_test_case(
257249 pretty_alg ,
258250 pretty_reason ,
259251 ' with ' + pretty_type if pretty_type else '' ))
260- dependencies = psa_information .automatic_dependencies (alg .base_expression , key_type )
261- dependencies = psa_information .fix_key_pair_dependencies (dependencies , 'BASIC' )
262- for i , dep in enumerate (dependencies ):
263- if dep in not_deps :
264- dependencies [i ] = '!' + dep
265252 tc .set_function (category .name .lower () + '_fail' )
266253 arguments = [] # type: List[str]
267254 if kt :
268255 bits = kt .sizes_to_test ()[0 ]
269256 tc .set_key_bits (bits )
257+ tc .set_key_pair_usage (['IMPORT' ])
270258 key_material = kt .key_material (bits )
271259 arguments += [key_type , test_case .hex_string (key_material )]
272260 arguments .append (alg .expression )
@@ -275,8 +263,25 @@ def make_test_case(
275263 error = ('NOT_SUPPORTED' if reason == self .Reason .NOT_SUPPORTED else
276264 'INVALID_ARGUMENT' )
277265 arguments .append ('PSA_ERROR_' + error )
266+ if reason == self .Reason .NOT_SUPPORTED :
267+ assert not_supported is not None
268+ tc .assumes_not_supported (not_supported )
269+ # Special case: if one of deterministic/randomized
270+ # ECDSA is supported but not the other, then the one
271+ # that is not supported in the signature direction is
272+ # still supported in the verification direction,
273+ # because the two verification algorithms are
274+ # identical. This property is how Mbed TLS chooses to
275+ # behave, the specification would also allow it to
276+ # reject the algorithm. In the generated test cases,
277+ # we avoid this difficulty by not running the
278+ # not-supported test case when exactly one of the
279+ # two variants is supported.
280+ if not_supported == 'PSA_WANT_ALG_ECDSA' :
281+ tc .add_dependencies (['!PSA_WANT_ALG_DETERMINISTIC_ECDSA' ])
282+ if not_supported == 'PSA_WANT_ALG_DETERMINISTIC_ECDSA' :
283+ tc .add_dependencies (['!PSA_WANT_ALG_ECDSA' ])
278284 tc .set_arguments (arguments )
279- tc .set_dependencies (dependencies )
280285 return tc
281286
282287 def no_key_test_cases (
@@ -290,7 +295,7 @@ def no_key_test_cases(
290295 for dep in psa_information .automatic_dependencies (alg .base_expression ):
291296 yield self .make_test_case (alg , category ,
292297 self .Reason .NOT_SUPPORTED ,
293- not_deps = frozenset ([ dep ]) )
298+ not_supported = dep )
294299 else :
295300 # Incompatible operation, supported algorithm
296301 yield self .make_test_case (alg , category , self .Reason .INVALID )
@@ -308,7 +313,7 @@ def one_key_test_cases(
308313 for dep in psa_information .automatic_dependencies (alg .base_expression ):
309314 yield self .make_test_case (alg , category ,
310315 self .Reason .NOT_SUPPORTED ,
311- kt = kt , not_deps = frozenset ([ dep ]) )
316+ kt = kt , not_supported = dep )
312317 # Public key for a private-key operation
313318 if category .is_asymmetric () and kt .is_public ():
314319 yield self .make_test_case (alg , category ,
@@ -481,7 +486,7 @@ def make_test_case(self, key: StorageTestData) -> test_case.TestCase:
481486 tc .add_dependencies (psa_information .generate_deps_from_description (key .description ))
482487 tc .set_function ('key_storage_' + verb )
483488 tc .set_key_bits (key .bits )
484- tc .set_key_pair_usage ('BASIC' )
489+ tc .set_key_pair_usage ([ 'IMPORT' ] if self . forward else [ 'EXPORT' ] )
485490 if self .forward :
486491 extra_arguments = []
487492 else :
0 commit comments