11
11
import enum
12
12
import re
13
13
import sys
14
- from typing import Callable , Dict , FrozenSet , Iterable , Iterator , List , Optional
14
+ from typing import Callable , Dict , Iterable , Iterator , List , Optional
15
15
16
16
from mbedtls_framework import crypto_data_tests
17
17
from mbedtls_framework import crypto_knowledge
26
26
27
27
def test_case_for_key_type_not_supported (
28
28
verb : str , key_type : str , bits : int ,
29
- dependencies : List [ str ] ,
29
+ not_supported_mechanism : str ,
30
30
* args : str ,
31
31
param_descr : str = ''
32
32
) -> test_case .TestCase :
@@ -35,17 +35,16 @@ def test_case_for_key_type_not_supported(
35
35
"""
36
36
tc = psa_test_case .TestCase ()
37
37
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( )
43
43
tc .set_function (verb + '_not_supported' )
44
44
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 )
46
47
tc .set_arguments ([key_type ] + list (args ))
47
- tc .set_dependencies (dependencies )
48
- tc .skip_if_any_not_implemented (dependencies )
49
48
return tc
50
49
51
50
class KeyTypeNotSupported :
@@ -77,37 +76,27 @@ def test_cases_for_key_type_not_supported(
77
76
# Don't generate test cases for key types that are always supported.
78
77
# They would be skipped in all configurations, which is noise.
79
78
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
88
81
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 ]
93
84
for bits in kt .sizes_to_test ():
94
85
yield test_case_for_key_type_not_supported (
95
86
'import' , kt .expression , bits ,
96
- psa_information . finish_family_dependencies ( import_dependencies , bits ) ,
87
+ not_supported_mechanism ,
97
88
test_case .hex_string (kt .key_material (bits )),
98
89
param_descr = param_descr ,
99
90
)
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.
107
96
if not kt .is_public ():
108
97
yield test_case_for_key_type_not_supported (
109
98
'generate' , kt .expression , bits ,
110
- psa_information . finish_family_dependencies ( generate_dependencies , bits ) ,
99
+ not_supported_mechanism ,
111
100
str (bits ),
112
101
param_descr = param_descr ,
113
102
)
@@ -155,7 +144,7 @@ def test_case_for_key_generation(
155
144
.format (short_key_type , bits ))
156
145
tc .set_function ('generate_key' )
157
146
tc .set_key_bits (bits )
158
- tc .set_key_pair_usage ('GENERATE' )
147
+ tc .set_key_pair_usage ([ 'GENERATE' ] )
159
148
tc .set_arguments ([key_type ] + list (args ) + [result ])
160
149
return tc
161
150
@@ -234,16 +223,19 @@ def make_test_case(
234
223
category : crypto_knowledge .AlgorithmCategory ,
235
224
reason : 'Reason' ,
236
225
kt : Optional [crypto_knowledge .KeyType ] = None ,
237
- not_deps : FrozenSet [str ] = frozenset () ,
226
+ not_supported : Optional [str ] = None ,
238
227
) -> 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
+ """
240
233
#pylint: disable=too-many-arguments,too-many-locals
241
234
tc = psa_test_case .TestCase ()
242
235
pretty_alg = alg .short_expression ()
243
236
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 )
247
239
else :
248
240
pretty_reason = reason .name .lower ()
249
241
if kt :
@@ -257,16 +249,12 @@ def make_test_case(
257
249
pretty_alg ,
258
250
pretty_reason ,
259
251
' 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
265
252
tc .set_function (category .name .lower () + '_fail' )
266
253
arguments = [] # type: List[str]
267
254
if kt :
268
255
bits = kt .sizes_to_test ()[0 ]
269
256
tc .set_key_bits (bits )
257
+ tc .set_key_pair_usage (['IMPORT' ])
270
258
key_material = kt .key_material (bits )
271
259
arguments += [key_type , test_case .hex_string (key_material )]
272
260
arguments .append (alg .expression )
@@ -275,8 +263,25 @@ def make_test_case(
275
263
error = ('NOT_SUPPORTED' if reason == self .Reason .NOT_SUPPORTED else
276
264
'INVALID_ARGUMENT' )
277
265
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' ])
278
284
tc .set_arguments (arguments )
279
- tc .set_dependencies (dependencies )
280
285
return tc
281
286
282
287
def no_key_test_cases (
@@ -290,7 +295,7 @@ def no_key_test_cases(
290
295
for dep in psa_information .automatic_dependencies (alg .base_expression ):
291
296
yield self .make_test_case (alg , category ,
292
297
self .Reason .NOT_SUPPORTED ,
293
- not_deps = frozenset ([ dep ]) )
298
+ not_supported = dep )
294
299
else :
295
300
# Incompatible operation, supported algorithm
296
301
yield self .make_test_case (alg , category , self .Reason .INVALID )
@@ -308,7 +313,7 @@ def one_key_test_cases(
308
313
for dep in psa_information .automatic_dependencies (alg .base_expression ):
309
314
yield self .make_test_case (alg , category ,
310
315
self .Reason .NOT_SUPPORTED ,
311
- kt = kt , not_deps = frozenset ([ dep ]) )
316
+ kt = kt , not_supported = dep )
312
317
# Public key for a private-key operation
313
318
if category .is_asymmetric () and kt .is_public ():
314
319
yield self .make_test_case (alg , category ,
@@ -481,7 +486,7 @@ def make_test_case(self, key: StorageTestData) -> test_case.TestCase:
481
486
tc .add_dependencies (psa_information .generate_deps_from_description (key .description ))
482
487
tc .set_function ('key_storage_' + verb )
483
488
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' ] )
485
490
if self .forward :
486
491
extra_arguments = []
487
492
else :
0 commit comments