blob: b6126477a910e2ee7e4c1efa1a32705a7f38bc2c [file] [log] [blame]
Gilles Peskine66e7b902021-02-12 23:40:58 +01001/** Code to exercise a PSA key object, i.e. validate that it seems well-formed
2 * and can do what it is supposed to do.
3 */
4
5/*
6 * Copyright The Mbed TLS Contributors
7 * SPDX-License-Identifier: Apache-2.0
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License"); you may
10 * not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 */
21
22#include <test/helpers.h>
23#include <test/macros.h>
Gilles Peskinee78b0022021-02-13 00:41:11 +010024#include <test/psa_exercise_key.h>
Gilles Peskine66e7b902021-02-12 23:40:58 +010025
26#if defined(MBEDTLS_PSA_CRYPTO_C)
27
Gilles Peskinee78b0022021-02-13 00:41:11 +010028#include <mbedtls/asn1.h>
Gilles Peskine66e7b902021-02-12 23:40:58 +010029#include <psa/crypto.h>
30
Gilles Peskinee78b0022021-02-13 00:41:11 +010031#include <test/asn1_helpers.h>
Przemyslaw Stekiel53de2622021-11-03 09:35:35 +010032#include <psa_crypto_slot_management.h>
Gilles Peskinee78b0022021-02-13 00:41:11 +010033#include <test/psa_crypto_helpers.h>
34
35#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
36static int lifetime_is_dynamic_secure_element( psa_key_lifetime_t lifetime )
37{
38 return( PSA_KEY_LIFETIME_GET_LOCATION( lifetime ) !=
39 PSA_KEY_LOCATION_LOCAL_STORAGE );
40}
41#endif
42
43static int check_key_attributes_sanity( mbedtls_svc_key_id_t key )
44{
45 int ok = 0;
46 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
47 psa_key_lifetime_t lifetime;
48 mbedtls_svc_key_id_t id;
49 psa_key_type_t type;
Gilles Peskine6b362e62021-02-15 12:03:16 +010050 size_t bits;
Gilles Peskinee78b0022021-02-13 00:41:11 +010051
52 PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
53 lifetime = psa_get_key_lifetime( &attributes );
54 id = psa_get_key_id( &attributes );
55 type = psa_get_key_type( &attributes );
56 bits = psa_get_key_bits( &attributes );
57
58 /* Persistence */
59 if( PSA_KEY_LIFETIME_IS_VOLATILE( lifetime ) )
60 {
61 TEST_ASSERT(
62 ( PSA_KEY_ID_VOLATILE_MIN <=
63 MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) ) &&
64 ( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) <=
65 PSA_KEY_ID_VOLATILE_MAX ) );
66 }
67 else
68 {
69 TEST_ASSERT(
70 ( PSA_KEY_ID_USER_MIN <= MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) ) &&
71 ( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) <= PSA_KEY_ID_USER_MAX ) );
72 }
73#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
74 /* randomly-generated 64-bit constant, should never appear in test data */
75 psa_key_slot_number_t slot_number = 0xec94d4a5058a1a21;
76 psa_status_t status = psa_get_key_slot_number( &attributes, &slot_number );
77 if( lifetime_is_dynamic_secure_element( lifetime ) )
78 {
79 /* Mbed Crypto currently always exposes the slot number to
80 * applications. This is not mandated by the PSA specification
81 * and may change in future versions. */
82 TEST_EQUAL( status, 0 );
83 TEST_ASSERT( slot_number != 0xec94d4a5058a1a21 );
84 }
85 else
86 {
87 TEST_EQUAL( status, PSA_ERROR_INVALID_ARGUMENT );
88 }
89#endif
90
91 /* Type and size */
92 TEST_ASSERT( type != 0 );
93 TEST_ASSERT( bits != 0 );
94 TEST_ASSERT( bits <= PSA_MAX_KEY_BITS );
95 if( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) )
96 TEST_ASSERT( bits % 8 == 0 );
97
98 /* MAX macros concerning specific key types */
99 if( PSA_KEY_TYPE_IS_ECC( type ) )
100 TEST_ASSERT( bits <= PSA_VENDOR_ECC_MAX_CURVE_BITS );
101 else if( PSA_KEY_TYPE_IS_RSA( type ) )
102 TEST_ASSERT( bits <= PSA_VENDOR_RSA_MAX_KEY_BITS );
103 TEST_ASSERT( PSA_BLOCK_CIPHER_BLOCK_LENGTH( type ) <= PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE );
104
105 ok = 1;
106
107exit:
108 /*
109 * Key attributes may have been returned by psa_get_key_attributes()
110 * thus reset them as required.
111 */
112 psa_reset_key_attributes( &attributes );
113
114 return( ok );
115}
116
117static int exercise_mac_key( mbedtls_svc_key_id_t key,
118 psa_key_usage_t usage,
119 psa_algorithm_t alg )
120{
121 psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
122 const unsigned char input[] = "foo";
123 unsigned char mac[PSA_MAC_MAX_SIZE] = {0};
124 size_t mac_length = sizeof( mac );
125
Steven Cooremanfb9cb922021-02-23 14:37:38 +0100126 /* Convert wildcard algorithm to exercisable algorithm */
127 if( alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG )
128 {
129 alg = PSA_ALG_TRUNCATED_MAC( alg, PSA_MAC_TRUNCATED_LENGTH( alg ) );
130 }
131
Gilles Peskinee78b0022021-02-13 00:41:11 +0100132 if( usage & PSA_KEY_USAGE_SIGN_HASH )
133 {
134 PSA_ASSERT( psa_mac_sign_setup( &operation, key, alg ) );
135 PSA_ASSERT( psa_mac_update( &operation,
136 input, sizeof( input ) ) );
137 PSA_ASSERT( psa_mac_sign_finish( &operation,
138 mac, sizeof( mac ),
139 &mac_length ) );
140 }
141
142 if( usage & PSA_KEY_USAGE_VERIFY_HASH )
143 {
144 psa_status_t verify_status =
145 ( usage & PSA_KEY_USAGE_SIGN_HASH ?
146 PSA_SUCCESS :
147 PSA_ERROR_INVALID_SIGNATURE );
148 PSA_ASSERT( psa_mac_verify_setup( &operation, key, alg ) );
149 PSA_ASSERT( psa_mac_update( &operation,
150 input, sizeof( input ) ) );
151 TEST_EQUAL( psa_mac_verify_finish( &operation, mac, mac_length ),
152 verify_status );
153 }
154
155 return( 1 );
156
157exit:
158 psa_mac_abort( &operation );
159 return( 0 );
160}
161
162static int exercise_cipher_key( mbedtls_svc_key_id_t key,
163 psa_key_usage_t usage,
164 psa_algorithm_t alg )
165{
166 psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
167 unsigned char iv[16] = {0};
168 size_t iv_length = sizeof( iv );
Gilles Peskinebbf452c2022-03-18 18:40:47 +0100169 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
170 psa_key_type_t key_type;
Gilles Peskinee78b0022021-02-13 00:41:11 +0100171 const unsigned char plaintext[16] = "Hello, world...";
172 unsigned char ciphertext[32] = "(wabblewebblewibblewobblewubble)";
173 size_t ciphertext_length = sizeof( ciphertext );
174 unsigned char decrypted[sizeof( ciphertext )];
175 size_t part_length;
176
Gilles Peskinebbf452c2022-03-18 18:40:47 +0100177 PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
178 key_type = psa_get_key_type( &attributes );
179 iv_length = PSA_CIPHER_IV_LENGTH( key_type, alg );
180
Gilles Peskinee78b0022021-02-13 00:41:11 +0100181 if( usage & PSA_KEY_USAGE_ENCRYPT )
182 {
183 PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
Gilles Peskinebbf452c2022-03-18 18:40:47 +0100184 if( PSA_CIPHER_IV_LENGTH( key_type, alg ) != 0 )
185 {
186 PSA_ASSERT( psa_cipher_generate_iv( &operation,
187 iv, sizeof( iv ),
188 &iv_length ) );
189 }
Gilles Peskinee78b0022021-02-13 00:41:11 +0100190 PSA_ASSERT( psa_cipher_update( &operation,
191 plaintext, sizeof( plaintext ),
192 ciphertext, sizeof( ciphertext ),
193 &ciphertext_length ) );
194 PSA_ASSERT( psa_cipher_finish( &operation,
195 ciphertext + ciphertext_length,
196 sizeof( ciphertext ) - ciphertext_length,
197 &part_length ) );
198 ciphertext_length += part_length;
199 }
200
201 if( usage & PSA_KEY_USAGE_DECRYPT )
202 {
203 psa_status_t status;
204 int maybe_invalid_padding = 0;
205 if( ! ( usage & PSA_KEY_USAGE_ENCRYPT ) )
206 {
Gilles Peskinee78b0022021-02-13 00:41:11 +0100207 maybe_invalid_padding = ! PSA_ALG_IS_STREAM_CIPHER( alg );
Gilles Peskinee78b0022021-02-13 00:41:11 +0100208 }
209 PSA_ASSERT( psa_cipher_decrypt_setup( &operation, key, alg ) );
Gilles Peskinebbf452c2022-03-18 18:40:47 +0100210 if( iv_length != 0 )
211 {
212 PSA_ASSERT( psa_cipher_set_iv( &operation,
213 iv, iv_length ) );
214 }
Gilles Peskinee78b0022021-02-13 00:41:11 +0100215 PSA_ASSERT( psa_cipher_update( &operation,
216 ciphertext, ciphertext_length,
217 decrypted, sizeof( decrypted ),
218 &part_length ) );
219 status = psa_cipher_finish( &operation,
220 decrypted + part_length,
221 sizeof( decrypted ) - part_length,
222 &part_length );
223 /* For a stream cipher, all inputs are valid. For a block cipher,
224 * if the input is some aribtrary data rather than an actual
225 ciphertext, a padding error is likely. */
226 if( maybe_invalid_padding )
227 TEST_ASSERT( status == PSA_SUCCESS ||
228 status == PSA_ERROR_INVALID_PADDING );
229 else
230 PSA_ASSERT( status );
231 }
232
233 return( 1 );
234
235exit:
236 psa_cipher_abort( &operation );
Gilles Peskinebbf452c2022-03-18 18:40:47 +0100237 psa_reset_key_attributes( &attributes );
Gilles Peskinee78b0022021-02-13 00:41:11 +0100238 return( 0 );
239}
240
241static int exercise_aead_key( mbedtls_svc_key_id_t key,
242 psa_key_usage_t usage,
243 psa_algorithm_t alg )
244{
245 unsigned char nonce[16] = {0};
246 size_t nonce_length = sizeof( nonce );
247 unsigned char plaintext[16] = "Hello, world...";
248 unsigned char ciphertext[48] = "(wabblewebblewibblewobblewubble)";
249 size_t ciphertext_length = sizeof( ciphertext );
250 size_t plaintext_length = sizeof( ciphertext );
251
Steven Cooremanfb9cb922021-02-23 14:37:38 +0100252 /* Convert wildcard algorithm to exercisable algorithm */
253 if( alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG )
254 {
255 alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, PSA_ALG_AEAD_GET_TAG_LENGTH( alg ) );
256 }
257
Gilles Peskinee78b0022021-02-13 00:41:11 +0100258 /* Default IV length for AES-GCM is 12 bytes */
259 if( PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 ) ==
260 PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ) )
261 {
262 nonce_length = 12;
263 }
264
Steven Cooremanaaec3412021-02-18 13:30:34 +0100265 /* IV length for CCM needs to be between 7 and 13 bytes */
266 if( PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 ) ==
267 PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 0 ) )
268 {
269 nonce_length = 12;
270 }
271
Gilles Peskinee78b0022021-02-13 00:41:11 +0100272 if( usage & PSA_KEY_USAGE_ENCRYPT )
273 {
274 PSA_ASSERT( psa_aead_encrypt( key, alg,
275 nonce, nonce_length,
276 NULL, 0,
277 plaintext, sizeof( plaintext ),
278 ciphertext, sizeof( ciphertext ),
279 &ciphertext_length ) );
280 }
281
282 if( usage & PSA_KEY_USAGE_DECRYPT )
283 {
284 psa_status_t verify_status =
285 ( usage & PSA_KEY_USAGE_ENCRYPT ?
286 PSA_SUCCESS :
287 PSA_ERROR_INVALID_SIGNATURE );
288 TEST_EQUAL( psa_aead_decrypt( key, alg,
289 nonce, nonce_length,
290 NULL, 0,
291 ciphertext, ciphertext_length,
292 plaintext, sizeof( plaintext ),
293 &plaintext_length ),
294 verify_status );
295 }
296
297 return( 1 );
298
299exit:
300 return( 0 );
301}
302
303static int exercise_signature_key( mbedtls_svc_key_id_t key,
304 psa_key_usage_t usage,
305 psa_algorithm_t alg )
306{
gabor-mezei-arm4c6a47a2021-04-26 20:12:17 +0200307 if( usage & ( PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH ) )
Gilles Peskinee78b0022021-02-13 00:41:11 +0100308 {
gabor-mezei-arm4c6a47a2021-04-26 20:12:17 +0200309 unsigned char payload[PSA_HASH_MAX_SIZE] = {1};
310 size_t payload_length = 16;
311 unsigned char signature[PSA_SIGNATURE_MAX_SIZE] = {0};
312 size_t signature_length = sizeof( signature );
313 psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg );
314
315 /* If the policy allows signing with any hash, just pick one. */
Gilles Peskinef7b41372021-09-22 16:15:05 +0200316 if( PSA_ALG_IS_SIGN_HASH( alg ) && hash_alg == PSA_ALG_ANY_HASH )
gabor-mezei-arm4c6a47a2021-04-26 20:12:17 +0200317 {
Ronald Cron4c0ec762021-08-31 19:08:55 +0200318 #if defined(KNOWN_MBEDTLS_SUPPORTED_HASH_ALG)
319 hash_alg = KNOWN_MBEDTLS_SUPPORTED_HASH_ALG;
gabor-mezei-arm4c6a47a2021-04-26 20:12:17 +0200320 alg ^= PSA_ALG_ANY_HASH ^ hash_alg;
321 #else
322 TEST_ASSERT( ! "No hash algorithm for hash-and-sign testing" );
323 #endif
324 }
325
Janos Follath4c0b60e2021-06-14 12:34:30 +0100326 /* Some algorithms require the payload to have the size of
327 * the hash encoded in the algorithm. Use this input size
328 * even for algorithms that allow other input sizes. */
329 if( hash_alg != 0 )
330 payload_length = PSA_HASH_LENGTH( hash_alg );
331
gabor-mezei-arm4c6a47a2021-04-26 20:12:17 +0200332 if( usage & PSA_KEY_USAGE_SIGN_HASH )
333 {
gabor-mezei-arm4c6a47a2021-04-26 20:12:17 +0200334 PSA_ASSERT( psa_sign_hash( key, alg,
335 payload, payload_length,
336 signature, sizeof( signature ),
337 &signature_length ) );
338 }
339
340 if( usage & PSA_KEY_USAGE_VERIFY_HASH )
341 {
342 psa_status_t verify_status =
343 ( usage & PSA_KEY_USAGE_SIGN_HASH ?
344 PSA_SUCCESS :
345 PSA_ERROR_INVALID_SIGNATURE );
346 TEST_EQUAL( psa_verify_hash( key, alg,
347 payload, payload_length,
348 signature, signature_length ),
349 verify_status );
350 }
Gilles Peskinee78b0022021-02-13 00:41:11 +0100351 }
352
gabor-mezei-arm4c6a47a2021-04-26 20:12:17 +0200353 if( usage & ( PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE ) )
Gilles Peskinee78b0022021-02-13 00:41:11 +0100354 {
gabor-mezei-arm4c6a47a2021-04-26 20:12:17 +0200355 unsigned char message[256] = "Hello, world...";
356 unsigned char signature[PSA_SIGNATURE_MAX_SIZE] = {0};
357 size_t message_length = 16;
358 size_t signature_length = sizeof( signature );
Gilles Peskinee78b0022021-02-13 00:41:11 +0100359
gabor-mezei-arm4c6a47a2021-04-26 20:12:17 +0200360 if( usage & PSA_KEY_USAGE_SIGN_MESSAGE )
361 {
362 PSA_ASSERT( psa_sign_message( key, alg,
363 message, message_length,
364 signature, sizeof( signature ),
365 &signature_length ) );
366 }
367
368 if( usage & PSA_KEY_USAGE_VERIFY_MESSAGE )
369 {
370 psa_status_t verify_status =
371 ( usage & PSA_KEY_USAGE_SIGN_MESSAGE ?
372 PSA_SUCCESS :
373 PSA_ERROR_INVALID_SIGNATURE );
374 TEST_EQUAL( psa_verify_message( key, alg,
375 message, message_length,
376 signature, signature_length ),
377 verify_status );
378 }
Gilles Peskinee78b0022021-02-13 00:41:11 +0100379 }
380
381 return( 1 );
382
383exit:
384 return( 0 );
385}
386
387static int exercise_asymmetric_encryption_key( mbedtls_svc_key_id_t key,
388 psa_key_usage_t usage,
389 psa_algorithm_t alg )
390{
391 unsigned char plaintext[256] = "Hello, world...";
392 unsigned char ciphertext[256] = "(wabblewebblewibblewobblewubble)";
393 size_t ciphertext_length = sizeof( ciphertext );
394 size_t plaintext_length = 16;
395
396 if( usage & PSA_KEY_USAGE_ENCRYPT )
397 {
398 PSA_ASSERT( psa_asymmetric_encrypt( key, alg,
399 plaintext, plaintext_length,
400 NULL, 0,
401 ciphertext, sizeof( ciphertext ),
402 &ciphertext_length ) );
403 }
404
405 if( usage & PSA_KEY_USAGE_DECRYPT )
406 {
407 psa_status_t status =
408 psa_asymmetric_decrypt( key, alg,
409 ciphertext, ciphertext_length,
410 NULL, 0,
411 plaintext, sizeof( plaintext ),
412 &plaintext_length );
413 TEST_ASSERT( status == PSA_SUCCESS ||
414 ( ( usage & PSA_KEY_USAGE_ENCRYPT ) == 0 &&
415 ( status == PSA_ERROR_INVALID_ARGUMENT ||
416 status == PSA_ERROR_INVALID_PADDING ) ) );
417 }
418
419 return( 1 );
420
421exit:
422 return( 0 );
423}
424
425int mbedtls_test_psa_setup_key_derivation_wrap(
426 psa_key_derivation_operation_t* operation,
427 mbedtls_svc_key_id_t key,
428 psa_algorithm_t alg,
Gilles Peskine5c2665b2021-02-14 01:22:56 +0100429 const unsigned char* input1, size_t input1_length,
430 const unsigned char* input2, size_t input2_length,
Gilles Peskinee78b0022021-02-13 00:41:11 +0100431 size_t capacity )
432{
433 PSA_ASSERT( psa_key_derivation_setup( operation, alg ) );
434 if( PSA_ALG_IS_HKDF( alg ) )
435 {
436 PSA_ASSERT( psa_key_derivation_input_bytes( operation,
437 PSA_KEY_DERIVATION_INPUT_SALT,
438 input1, input1_length ) );
439 PSA_ASSERT( psa_key_derivation_input_key( operation,
440 PSA_KEY_DERIVATION_INPUT_SECRET,
441 key ) );
442 PSA_ASSERT( psa_key_derivation_input_bytes( operation,
443 PSA_KEY_DERIVATION_INPUT_INFO,
444 input2,
445 input2_length ) );
446 }
447 else if( PSA_ALG_IS_TLS12_PRF( alg ) ||
448 PSA_ALG_IS_TLS12_PSK_TO_MS( alg ) )
449 {
450 PSA_ASSERT( psa_key_derivation_input_bytes( operation,
451 PSA_KEY_DERIVATION_INPUT_SEED,
452 input1, input1_length ) );
453 PSA_ASSERT( psa_key_derivation_input_key( operation,
454 PSA_KEY_DERIVATION_INPUT_SECRET,
455 key ) );
456 PSA_ASSERT( psa_key_derivation_input_bytes( operation,
457 PSA_KEY_DERIVATION_INPUT_LABEL,
458 input2, input2_length ) );
459 }
460 else
461 {
462 TEST_ASSERT( ! "Key derivation algorithm not supported" );
463 }
464
465 if( capacity != SIZE_MAX )
466 PSA_ASSERT( psa_key_derivation_set_capacity( operation, capacity ) );
467
468 return( 1 );
469
470exit:
471 return( 0 );
472}
473
474
475static int exercise_key_derivation_key( mbedtls_svc_key_id_t key,
476 psa_key_usage_t usage,
477 psa_algorithm_t alg )
478{
479 psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
480 unsigned char input1[] = "Input 1";
481 size_t input1_length = sizeof( input1 );
482 unsigned char input2[] = "Input 2";
483 size_t input2_length = sizeof( input2 );
484 unsigned char output[1];
485 size_t capacity = sizeof( output );
486
487 if( usage & PSA_KEY_USAGE_DERIVE )
488 {
489 if( !mbedtls_test_psa_setup_key_derivation_wrap( &operation, key, alg,
490 input1, input1_length,
491 input2, input2_length,
492 capacity ) )
493 goto exit;
494
495 PSA_ASSERT( psa_key_derivation_output_bytes( &operation,
496 output,
497 capacity ) );
498 PSA_ASSERT( psa_key_derivation_abort( &operation ) );
499 }
500
501 return( 1 );
502
503exit:
504 return( 0 );
505}
506
507/* We need two keys to exercise key agreement. Exercise the
508 * private key against its own public key. */
509psa_status_t mbedtls_test_psa_key_agreement_with_self(
510 psa_key_derivation_operation_t *operation,
511 mbedtls_svc_key_id_t key )
512{
513 psa_key_type_t private_key_type;
514 psa_key_type_t public_key_type;
515 size_t key_bits;
516 uint8_t *public_key = NULL;
517 size_t public_key_length;
518 /* Return GENERIC_ERROR if something other than the final call to
519 * psa_key_derivation_key_agreement fails. This isn't fully satisfactory,
520 * but it's good enough: callers will report it as a failed test anyway. */
521 psa_status_t status = PSA_ERROR_GENERIC_ERROR;
522 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
523
524 PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
525 private_key_type = psa_get_key_type( &attributes );
526 key_bits = psa_get_key_bits( &attributes );
527 public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR( private_key_type );
gabor-mezei-armceface22021-01-21 12:26:17 +0100528 public_key_length = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( public_key_type, key_bits );
Gilles Peskinee78b0022021-02-13 00:41:11 +0100529 ASSERT_ALLOC( public_key, public_key_length );
530 PSA_ASSERT( psa_export_public_key( key, public_key, public_key_length,
531 &public_key_length ) );
532
533 status = psa_key_derivation_key_agreement(
534 operation, PSA_KEY_DERIVATION_INPUT_SECRET, key,
535 public_key, public_key_length );
536exit:
537 /*
538 * Key attributes may have been returned by psa_get_key_attributes()
539 * thus reset them as required.
540 */
541 psa_reset_key_attributes( &attributes );
542
543 mbedtls_free( public_key );
544 return( status );
545}
546
547/* We need two keys to exercise key agreement. Exercise the
548 * private key against its own public key. */
549psa_status_t mbedtls_test_psa_raw_key_agreement_with_self(
550 psa_algorithm_t alg,
551 mbedtls_svc_key_id_t key )
552{
553 psa_key_type_t private_key_type;
554 psa_key_type_t public_key_type;
555 size_t key_bits;
556 uint8_t *public_key = NULL;
557 size_t public_key_length;
558 uint8_t output[1024];
559 size_t output_length;
560 /* Return GENERIC_ERROR if something other than the final call to
561 * psa_key_derivation_key_agreement fails. This isn't fully satisfactory,
562 * but it's good enough: callers will report it as a failed test anyway. */
563 psa_status_t status = PSA_ERROR_GENERIC_ERROR;
564 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
565
566 PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
567 private_key_type = psa_get_key_type( &attributes );
568 key_bits = psa_get_key_bits( &attributes );
569 public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR( private_key_type );
gabor-mezei-armceface22021-01-21 12:26:17 +0100570 public_key_length = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( public_key_type, key_bits );
Gilles Peskinee78b0022021-02-13 00:41:11 +0100571 ASSERT_ALLOC( public_key, public_key_length );
572 PSA_ASSERT( psa_export_public_key( key,
573 public_key, public_key_length,
574 &public_key_length ) );
575
576 status = psa_raw_key_agreement( alg, key,
577 public_key, public_key_length,
578 output, sizeof( output ), &output_length );
gabor-mezei-armceface22021-01-21 12:26:17 +0100579 if ( status == PSA_SUCCESS )
580 {
581 TEST_ASSERT( output_length <=
582 PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE( private_key_type,
583 key_bits ) );
584 TEST_ASSERT( output_length <=
585 PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE );
586 }
587
Gilles Peskinee78b0022021-02-13 00:41:11 +0100588exit:
589 /*
590 * Key attributes may have been returned by psa_get_key_attributes()
591 * thus reset them as required.
592 */
593 psa_reset_key_attributes( &attributes );
594
595 mbedtls_free( public_key );
596 return( status );
597}
598
599static int exercise_raw_key_agreement_key( mbedtls_svc_key_id_t key,
600 psa_key_usage_t usage,
601 psa_algorithm_t alg )
602{
603 int ok = 0;
604
605 if( usage & PSA_KEY_USAGE_DERIVE )
606 {
607 /* We need two keys to exercise key agreement. Exercise the
608 * private key against its own public key. */
609 PSA_ASSERT( mbedtls_test_psa_raw_key_agreement_with_self( alg, key ) );
610 }
611 ok = 1;
612
613exit:
614 return( ok );
615}
616
617static int exercise_key_agreement_key( mbedtls_svc_key_id_t key,
618 psa_key_usage_t usage,
619 psa_algorithm_t alg )
620{
621 psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
622 unsigned char output[1];
623 int ok = 0;
624
625 if( usage & PSA_KEY_USAGE_DERIVE )
626 {
627 /* We need two keys to exercise key agreement. Exercise the
628 * private key against its own public key. */
629 PSA_ASSERT( psa_key_derivation_setup( &operation, alg ) );
630 PSA_ASSERT( mbedtls_test_psa_key_agreement_with_self( &operation, key ) );
631 PSA_ASSERT( psa_key_derivation_output_bytes( &operation,
632 output,
633 sizeof( output ) ) );
634 PSA_ASSERT( psa_key_derivation_abort( &operation ) );
635 }
636 ok = 1;
637
638exit:
639 return( ok );
640}
641
642int mbedtls_test_psa_exported_key_sanity_check(
643 psa_key_type_t type, size_t bits,
Gilles Peskine5c2665b2021-02-14 01:22:56 +0100644 const uint8_t *exported, size_t exported_length )
Gilles Peskinee78b0022021-02-13 00:41:11 +0100645{
Gilles Peskinecc9db302021-02-14 01:29:52 +0100646 TEST_ASSERT( exported_length <= PSA_EXPORT_KEY_OUTPUT_SIZE( type, bits ) );
Gilles Peskinee78b0022021-02-13 00:41:11 +0100647
Gilles Peskinecc9db302021-02-14 01:29:52 +0100648 if( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) )
649 TEST_EQUAL( exported_length, PSA_BITS_TO_BYTES( bits ) );
Gilles Peskinee78b0022021-02-13 00:41:11 +0100650 else
Gilles Peskinee78b0022021-02-13 00:41:11 +0100651
Ronald Cron64df7382021-07-06 09:23:06 +0200652#if defined(MBEDTLS_ASN1_PARSE_C)
Gilles Peskinee78b0022021-02-13 00:41:11 +0100653 if( type == PSA_KEY_TYPE_RSA_KEY_PAIR )
654 {
Gilles Peskine5c2665b2021-02-14 01:22:56 +0100655 uint8_t *p = (uint8_t*) exported;
656 const uint8_t *end = exported + exported_length;
Gilles Peskinee78b0022021-02-13 00:41:11 +0100657 size_t len;
658 /* RSAPrivateKey ::= SEQUENCE {
659 * version INTEGER, -- must be 0
660 * modulus INTEGER, -- n
661 * publicExponent INTEGER, -- e
662 * privateExponent INTEGER, -- d
663 * prime1 INTEGER, -- p
664 * prime2 INTEGER, -- q
665 * exponent1 INTEGER, -- d mod (p-1)
666 * exponent2 INTEGER, -- d mod (q-1)
667 * coefficient INTEGER, -- (inverse of q) mod p
668 * }
669 */
670 TEST_EQUAL( mbedtls_asn1_get_tag( &p, end, &len,
671 MBEDTLS_ASN1_SEQUENCE |
672 MBEDTLS_ASN1_CONSTRUCTED ), 0 );
Gilles Peskine89615ee2021-04-29 20:28:54 +0200673 TEST_EQUAL( len, end - p );
Gilles Peskinee78b0022021-02-13 00:41:11 +0100674 if( ! mbedtls_test_asn1_skip_integer( &p, end, 0, 0, 0 ) )
675 goto exit;
676 if( ! mbedtls_test_asn1_skip_integer( &p, end, bits, bits, 1 ) )
677 goto exit;
678 if( ! mbedtls_test_asn1_skip_integer( &p, end, 2, bits, 1 ) )
679 goto exit;
680 /* Require d to be at least half the size of n. */
681 if( ! mbedtls_test_asn1_skip_integer( &p, end, bits / 2, bits, 1 ) )
682 goto exit;
683 /* Require p and q to be at most half the size of n, rounded up. */
684 if( ! mbedtls_test_asn1_skip_integer( &p, end, bits / 2, bits / 2 + 1, 1 ) )
685 goto exit;
686 if( ! mbedtls_test_asn1_skip_integer( &p, end, bits / 2, bits / 2 + 1, 1 ) )
687 goto exit;
688 if( ! mbedtls_test_asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
689 goto exit;
690 if( ! mbedtls_test_asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
691 goto exit;
692 if( ! mbedtls_test_asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
693 goto exit;
Gilles Peskine89615ee2021-04-29 20:28:54 +0200694 TEST_EQUAL( p - end, 0 );
gabor-mezei-armceface22021-01-21 12:26:17 +0100695
696 TEST_ASSERT( exported_length <= PSA_EXPORT_KEY_PAIR_MAX_SIZE );
Gilles Peskinee78b0022021-02-13 00:41:11 +0100697 }
698 else
Ronald Cron64df7382021-07-06 09:23:06 +0200699#endif /* MBEDTLS_ASN1_PARSE_C */
Gilles Peskinee78b0022021-02-13 00:41:11 +0100700
701#if defined(MBEDTLS_ECP_C)
702 if( PSA_KEY_TYPE_IS_ECC_KEY_PAIR( type ) )
703 {
704 /* Just the secret value */
705 TEST_EQUAL( exported_length, PSA_BITS_TO_BYTES( bits ) );
gabor-mezei-armceface22021-01-21 12:26:17 +0100706
707 TEST_ASSERT( exported_length <= PSA_EXPORT_KEY_PAIR_MAX_SIZE );
Gilles Peskinee78b0022021-02-13 00:41:11 +0100708 }
709 else
710#endif /* MBEDTLS_ECP_C */
711
Ronald Cron64df7382021-07-06 09:23:06 +0200712#if defined(MBEDTLS_ASN1_PARSE_C)
Gilles Peskinead557e52021-02-14 01:19:21 +0100713 if( type == PSA_KEY_TYPE_RSA_PUBLIC_KEY )
Gilles Peskinee78b0022021-02-13 00:41:11 +0100714 {
Gilles Peskine5c2665b2021-02-14 01:22:56 +0100715 uint8_t *p = (uint8_t*) exported;
716 const uint8_t *end = exported + exported_length;
Gilles Peskinead557e52021-02-14 01:19:21 +0100717 size_t len;
718 /* RSAPublicKey ::= SEQUENCE {
719 * modulus INTEGER, -- n
720 * publicExponent INTEGER } -- e
721 */
722 TEST_EQUAL( mbedtls_asn1_get_tag( &p, end, &len,
723 MBEDTLS_ASN1_SEQUENCE |
724 MBEDTLS_ASN1_CONSTRUCTED ),
725 0 );
Gilles Peskine89615ee2021-04-29 20:28:54 +0200726 TEST_EQUAL( len, end - p );
Gilles Peskinead557e52021-02-14 01:19:21 +0100727 if( ! mbedtls_test_asn1_skip_integer( &p, end, bits, bits, 1 ) )
728 goto exit;
729 if( ! mbedtls_test_asn1_skip_integer( &p, end, 2, bits, 1 ) )
730 goto exit;
Gilles Peskine89615ee2021-04-29 20:28:54 +0200731 TEST_EQUAL( p - end, 0 );
gabor-mezei-armceface22021-01-21 12:26:17 +0100732
733
734 TEST_ASSERT( exported_length <=
735 PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( type, bits ) );
736 TEST_ASSERT( exported_length <=
737 PSA_EXPORT_PUBLIC_KEY_MAX_SIZE );
Gilles Peskinead557e52021-02-14 01:19:21 +0100738 }
739 else
Ronald Cron64df7382021-07-06 09:23:06 +0200740#endif /* MBEDTLS_ASN1_PARSE_C */
Gilles Peskinead557e52021-02-14 01:19:21 +0100741
Gilles Peskinee78b0022021-02-13 00:41:11 +0100742#if defined(MBEDTLS_ECP_C)
Gilles Peskinead557e52021-02-14 01:19:21 +0100743 if( PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( type ) )
744 {
gabor-mezei-armceface22021-01-21 12:26:17 +0100745
746 TEST_ASSERT( exported_length <=
747 PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( type, bits ) );
748 TEST_ASSERT( exported_length <=
749 PSA_EXPORT_PUBLIC_KEY_MAX_SIZE );
750
Gilles Peskinead557e52021-02-14 01:19:21 +0100751 if( PSA_KEY_TYPE_ECC_GET_FAMILY( type ) == PSA_ECC_FAMILY_MONTGOMERY )
Gilles Peskinee78b0022021-02-13 00:41:11 +0100752 {
Gilles Peskinead557e52021-02-14 01:19:21 +0100753 /* The representation of an ECC Montgomery public key is
754 * the raw compressed point */
755 TEST_EQUAL( PSA_BITS_TO_BYTES( bits ), exported_length );
Gilles Peskinee78b0022021-02-13 00:41:11 +0100756 }
757 else
Gilles Peskinee78b0022021-02-13 00:41:11 +0100758 {
Gilles Peskinead557e52021-02-14 01:19:21 +0100759 /* The representation of an ECC Weierstrass public key is:
760 * - The byte 0x04;
761 * - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
762 * - `y_P` as a `ceiling(m/8)`-byte string, big-endian;
763 * - where m is the bit size associated with the curve.
764 */
765 TEST_EQUAL( 1 + 2 * PSA_BITS_TO_BYTES( bits ), exported_length );
766 TEST_EQUAL( exported[0], 4 );
Gilles Peskinee78b0022021-02-13 00:41:11 +0100767 }
768 }
769 else
Gilles Peskinead557e52021-02-14 01:19:21 +0100770#endif /* MBEDTLS_ECP_C */
771
Gilles Peskinead557e52021-02-14 01:19:21 +0100772 {
Andrzej Kurek57d2f132022-01-17 15:26:24 +0100773 (void) exported;
Gilles Peskinecc9db302021-02-14 01:29:52 +0100774 TEST_ASSERT( ! "Sanity check not implemented for this key type" );
Gilles Peskinead557e52021-02-14 01:19:21 +0100775 }
Gilles Peskinee78b0022021-02-13 00:41:11 +0100776
Gilles Peskinecc9db302021-02-14 01:29:52 +0100777#if defined(MBEDTLS_DES_C)
778 if( type == PSA_KEY_TYPE_DES )
Gilles Peskinee78b0022021-02-13 00:41:11 +0100779 {
Gilles Peskinecc9db302021-02-14 01:29:52 +0100780 /* Check the parity bits. */
781 unsigned i;
782 for( i = 0; i < bits / 8; i++ )
783 {
784 unsigned bit_count = 0;
785 unsigned m;
786 for( m = 1; m <= 0x100; m <<= 1 )
787 {
788 if( exported[i] & m )
789 ++bit_count;
790 }
791 TEST_ASSERT( bit_count % 2 != 0 );
792 }
Gilles Peskinee78b0022021-02-13 00:41:11 +0100793 }
Gilles Peskinecc9db302021-02-14 01:29:52 +0100794#endif
Gilles Peskinee78b0022021-02-13 00:41:11 +0100795
796 return( 1 );
797
798exit:
799 return( 0 );
800}
801
802static int exercise_export_key( mbedtls_svc_key_id_t key,
803 psa_key_usage_t usage )
804{
805 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
806 uint8_t *exported = NULL;
807 size_t exported_size = 0;
808 size_t exported_length = 0;
809 int ok = 0;
810
811 PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
812
813 exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
814 psa_get_key_type( &attributes ),
815 psa_get_key_bits( &attributes ) );
816 ASSERT_ALLOC( exported, exported_size );
817
818 if( ( usage & PSA_KEY_USAGE_EXPORT ) == 0 &&
819 ! PSA_KEY_TYPE_IS_PUBLIC_KEY( psa_get_key_type( &attributes ) ) )
820 {
821 TEST_EQUAL( psa_export_key( key, exported,
822 exported_size, &exported_length ),
823 PSA_ERROR_NOT_PERMITTED );
824 ok = 1;
825 goto exit;
826 }
827
828 PSA_ASSERT( psa_export_key( key,
829 exported, exported_size,
830 &exported_length ) );
831 ok = mbedtls_test_psa_exported_key_sanity_check(
832 psa_get_key_type( &attributes ), psa_get_key_bits( &attributes ),
833 exported, exported_length );
834
835exit:
836 /*
837 * Key attributes may have been returned by psa_get_key_attributes()
838 * thus reset them as required.
839 */
840 psa_reset_key_attributes( &attributes );
841
842 mbedtls_free( exported );
843 return( ok );
844}
845
846static int exercise_export_public_key( mbedtls_svc_key_id_t key )
847{
848 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
849 psa_key_type_t public_type;
850 uint8_t *exported = NULL;
851 size_t exported_size = 0;
852 size_t exported_length = 0;
853 int ok = 0;
854
855 PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
856 if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( psa_get_key_type( &attributes ) ) )
857 {
858 exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
859 psa_get_key_type( &attributes ),
860 psa_get_key_bits( &attributes ) );
861 ASSERT_ALLOC( exported, exported_size );
862
863 TEST_EQUAL( psa_export_public_key( key, exported,
864 exported_size, &exported_length ),
865 PSA_ERROR_INVALID_ARGUMENT );
866 ok = 1;
867 goto exit;
868 }
869
870 public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(
871 psa_get_key_type( &attributes ) );
gabor-mezei-armceface22021-01-21 12:26:17 +0100872 exported_size = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( public_type,
873 psa_get_key_bits( &attributes ) );
Gilles Peskinee78b0022021-02-13 00:41:11 +0100874 ASSERT_ALLOC( exported, exported_size );
875
876 PSA_ASSERT( psa_export_public_key( key,
877 exported, exported_size,
878 &exported_length ) );
879 ok = mbedtls_test_psa_exported_key_sanity_check(
880 public_type, psa_get_key_bits( &attributes ),
881 exported, exported_length );
882
883exit:
884 /*
885 * Key attributes may have been returned by psa_get_key_attributes()
886 * thus reset them as required.
887 */
888 psa_reset_key_attributes( &attributes );
889
890 mbedtls_free( exported );
891 return( ok );
892}
893
894int mbedtls_test_psa_exercise_key( mbedtls_svc_key_id_t key,
895 psa_key_usage_t usage,
896 psa_algorithm_t alg )
897{
Gilles Peskine2385f712021-02-14 01:34:21 +0100898 int ok = 0;
Gilles Peskinee78b0022021-02-13 00:41:11 +0100899
900 if( ! check_key_attributes_sanity( key ) )
901 return( 0 );
902
903 if( alg == 0 )
904 ok = 1; /* If no algorihm, do nothing (used for raw data "keys"). */
905 else if( PSA_ALG_IS_MAC( alg ) )
906 ok = exercise_mac_key( key, usage, alg );
907 else if( PSA_ALG_IS_CIPHER( alg ) )
908 ok = exercise_cipher_key( key, usage, alg );
909 else if( PSA_ALG_IS_AEAD( alg ) )
910 ok = exercise_aead_key( key, usage, alg );
911 else if( PSA_ALG_IS_SIGN( alg ) )
912 ok = exercise_signature_key( key, usage, alg );
913 else if( PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) )
914 ok = exercise_asymmetric_encryption_key( key, usage, alg );
915 else if( PSA_ALG_IS_KEY_DERIVATION( alg ) )
916 ok = exercise_key_derivation_key( key, usage, alg );
917 else if( PSA_ALG_IS_RAW_KEY_AGREEMENT( alg ) )
918 ok = exercise_raw_key_agreement_key( key, usage, alg );
919 else if( PSA_ALG_IS_KEY_AGREEMENT( alg ) )
920 ok = exercise_key_agreement_key( key, usage, alg );
921 else
Gilles Peskine2385f712021-02-14 01:34:21 +0100922 TEST_ASSERT( ! "No code to exercise this category of algorithm" );
Gilles Peskinee78b0022021-02-13 00:41:11 +0100923
924 ok = ok && exercise_export_key( key, usage );
925 ok = ok && exercise_export_public_key( key );
926
Gilles Peskine2385f712021-02-14 01:34:21 +0100927exit:
Gilles Peskinee78b0022021-02-13 00:41:11 +0100928 return( ok );
929}
930
931psa_key_usage_t mbedtls_test_psa_usage_to_exercise( psa_key_type_t type,
932 psa_algorithm_t alg )
933{
934 if( PSA_ALG_IS_MAC( alg ) || PSA_ALG_IS_SIGN( alg ) )
935 {
Gilles Peskinef7b41372021-09-22 16:15:05 +0200936 if( PSA_ALG_IS_SIGN_HASH( alg ) )
gabor-mezei-arm041887b2021-05-11 13:29:24 +0200937 {
938 if( PSA_ALG_SIGN_GET_HASH( alg ) )
939 return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
940 PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:
941 PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH |
942 PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE );
943 }
944 else if( PSA_ALG_IS_SIGN_MESSAGE( alg) )
gabor-mezei-arm4c6a47a2021-04-26 20:12:17 +0200945 return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
gabor-mezei-arm041887b2021-05-11 13:29:24 +0200946 PSA_KEY_USAGE_VERIFY_MESSAGE :
gabor-mezei-arm4c6a47a2021-04-26 20:12:17 +0200947 PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE );
948
gabor-mezei-arm041887b2021-05-11 13:29:24 +0200949 return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
950 PSA_KEY_USAGE_VERIFY_HASH :
951 PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH );
Gilles Peskinee78b0022021-02-13 00:41:11 +0100952 }
953 else if( PSA_ALG_IS_CIPHER( alg ) || PSA_ALG_IS_AEAD( alg ) ||
954 PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) )
955 {
956 return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
957 PSA_KEY_USAGE_ENCRYPT :
958 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
959 }
960 else if( PSA_ALG_IS_KEY_DERIVATION( alg ) ||
961 PSA_ALG_IS_KEY_AGREEMENT( alg ) )
962 {
963 return( PSA_KEY_USAGE_DERIVE );
964 }
965 else
966 {
967 return( 0 );
968 }
969
970}
Gilles Peskine66e7b902021-02-12 23:40:58 +0100971
972#endif /* MBEDTLS_PSA_CRYPTO_C */