• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** 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>
24 #include <test/psa_exercise_key.h>
25 
26 #if defined(MBEDTLS_PSA_CRYPTO_C)
27 
28 #include <mbedtls/asn1.h>
29 #include <psa/crypto.h>
30 
31 #include <test/asn1_helpers.h>
32 #include <psa_crypto_slot_management.h>
33 #include <test/psa_crypto_helpers.h>
34 
35 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
lifetime_is_dynamic_secure_element(psa_key_lifetime_t lifetime)36 static 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 
check_key_attributes_sanity(mbedtls_svc_key_id_t key)43 static 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;
50     size_t bits;
51 
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 
107 exit:
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 
exercise_mac_key(mbedtls_svc_key_id_t key,psa_key_usage_t usage,psa_algorithm_t alg)117 static 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 
126     /* 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 
132     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 
157 exit:
158     psa_mac_abort( &operation );
159     return( 0 );
160 }
161 
exercise_cipher_key(mbedtls_svc_key_id_t key,psa_key_usage_t usage,psa_algorithm_t alg)162 static 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 );
169     const unsigned char plaintext[16] = "Hello, world...";
170     unsigned char ciphertext[32] = "(wabblewebblewibblewobblewubble)";
171     size_t ciphertext_length = sizeof( ciphertext );
172     unsigned char decrypted[sizeof( ciphertext )];
173     size_t part_length;
174 
175     if( usage & PSA_KEY_USAGE_ENCRYPT )
176     {
177         PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
178         PSA_ASSERT( psa_cipher_generate_iv( &operation,
179                                             iv, sizeof( iv ),
180                                             &iv_length ) );
181         PSA_ASSERT( psa_cipher_update( &operation,
182                                        plaintext, sizeof( plaintext ),
183                                        ciphertext, sizeof( ciphertext ),
184                                        &ciphertext_length ) );
185         PSA_ASSERT( psa_cipher_finish( &operation,
186                                        ciphertext + ciphertext_length,
187                                        sizeof( ciphertext ) - ciphertext_length,
188                                        &part_length ) );
189         ciphertext_length += part_length;
190     }
191 
192     if( usage & PSA_KEY_USAGE_DECRYPT )
193     {
194         psa_status_t status;
195         int maybe_invalid_padding = 0;
196         if( ! ( usage & PSA_KEY_USAGE_ENCRYPT ) )
197         {
198             psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
199             PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
200             /* This should be PSA_CIPHER_GET_IV_SIZE but the API doesn't
201              * have this macro yet. */
202             iv_length = PSA_BLOCK_CIPHER_BLOCK_LENGTH(
203                 psa_get_key_type( &attributes ) );
204             maybe_invalid_padding = ! PSA_ALG_IS_STREAM_CIPHER( alg );
205             psa_reset_key_attributes( &attributes );
206         }
207         PSA_ASSERT( psa_cipher_decrypt_setup( &operation, key, alg ) );
208         PSA_ASSERT( psa_cipher_set_iv( &operation,
209                                        iv, iv_length ) );
210         PSA_ASSERT( psa_cipher_update( &operation,
211                                        ciphertext, ciphertext_length,
212                                        decrypted, sizeof( decrypted ),
213                                        &part_length ) );
214         status = psa_cipher_finish( &operation,
215                                     decrypted + part_length,
216                                     sizeof( decrypted ) - part_length,
217                                     &part_length );
218         /* For a stream cipher, all inputs are valid. For a block cipher,
219          * if the input is some aribtrary data rather than an actual
220          ciphertext, a padding error is likely.  */
221         if( maybe_invalid_padding )
222             TEST_ASSERT( status == PSA_SUCCESS ||
223                          status == PSA_ERROR_INVALID_PADDING );
224         else
225             PSA_ASSERT( status );
226     }
227 
228     return( 1 );
229 
230 exit:
231     psa_cipher_abort( &operation );
232     return( 0 );
233 }
234 
exercise_aead_key(mbedtls_svc_key_id_t key,psa_key_usage_t usage,psa_algorithm_t alg)235 static int exercise_aead_key( mbedtls_svc_key_id_t key,
236                               psa_key_usage_t usage,
237                               psa_algorithm_t alg )
238 {
239     unsigned char nonce[16] = {0};
240     size_t nonce_length = sizeof( nonce );
241     unsigned char plaintext[16] = "Hello, world...";
242     unsigned char ciphertext[48] = "(wabblewebblewibblewobblewubble)";
243     size_t ciphertext_length = sizeof( ciphertext );
244     size_t plaintext_length = sizeof( ciphertext );
245 
246     /* Convert wildcard algorithm to exercisable algorithm */
247     if( alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG )
248     {
249         alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, PSA_ALG_AEAD_GET_TAG_LENGTH( alg ) );
250     }
251 
252     /* Default IV length for AES-GCM is 12 bytes */
253     if( PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 ) ==
254         PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ) )
255     {
256         nonce_length = 12;
257     }
258 
259     /* IV length for CCM needs to be between 7 and 13 bytes */
260     if( PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 ) ==
261         PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 0 ) )
262     {
263         nonce_length = 12;
264     }
265 
266     if( usage & PSA_KEY_USAGE_ENCRYPT )
267     {
268         PSA_ASSERT( psa_aead_encrypt( key, alg,
269                                       nonce, nonce_length,
270                                       NULL, 0,
271                                       plaintext, sizeof( plaintext ),
272                                       ciphertext, sizeof( ciphertext ),
273                                       &ciphertext_length ) );
274     }
275 
276     if( usage & PSA_KEY_USAGE_DECRYPT )
277     {
278         psa_status_t verify_status =
279             ( usage & PSA_KEY_USAGE_ENCRYPT ?
280               PSA_SUCCESS :
281               PSA_ERROR_INVALID_SIGNATURE );
282         TEST_EQUAL( psa_aead_decrypt( key, alg,
283                                       nonce, nonce_length,
284                                       NULL, 0,
285                                       ciphertext, ciphertext_length,
286                                       plaintext, sizeof( plaintext ),
287                                       &plaintext_length ),
288                     verify_status );
289     }
290 
291     return( 1 );
292 
293 exit:
294     return( 0 );
295 }
296 
exercise_signature_key(mbedtls_svc_key_id_t key,psa_key_usage_t usage,psa_algorithm_t alg)297 static int exercise_signature_key( mbedtls_svc_key_id_t key,
298                                    psa_key_usage_t usage,
299                                    psa_algorithm_t alg )
300 {
301     if( usage & ( PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH ) )
302     {
303         unsigned char payload[PSA_HASH_MAX_SIZE] = {1};
304         size_t payload_length = 16;
305         unsigned char signature[PSA_SIGNATURE_MAX_SIZE] = {0};
306         size_t signature_length = sizeof( signature );
307         psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg );
308 
309         /* If the policy allows signing with any hash, just pick one. */
310         if( PSA_ALG_IS_SIGN_HASH( alg ) && hash_alg == PSA_ALG_ANY_HASH )
311         {
312     #if defined(KNOWN_MBEDTLS_SUPPORTED_HASH_ALG)
313             hash_alg = KNOWN_MBEDTLS_SUPPORTED_HASH_ALG;
314             alg ^= PSA_ALG_ANY_HASH ^ hash_alg;
315     #else
316             TEST_ASSERT( ! "No hash algorithm for hash-and-sign testing" );
317     #endif
318         }
319 
320         /* Some algorithms require the payload to have the size of
321          * the hash encoded in the algorithm. Use this input size
322          * even for algorithms that allow other input sizes. */
323         if( hash_alg != 0 )
324             payload_length = PSA_HASH_LENGTH( hash_alg );
325 
326         if( usage & PSA_KEY_USAGE_SIGN_HASH )
327         {
328             PSA_ASSERT( psa_sign_hash( key, alg,
329                                        payload, payload_length,
330                                        signature, sizeof( signature ),
331                                        &signature_length ) );
332         }
333 
334         if( usage & PSA_KEY_USAGE_VERIFY_HASH )
335         {
336             psa_status_t verify_status =
337                 ( usage & PSA_KEY_USAGE_SIGN_HASH ?
338                   PSA_SUCCESS :
339                   PSA_ERROR_INVALID_SIGNATURE );
340             TEST_EQUAL( psa_verify_hash( key, alg,
341                                          payload, payload_length,
342                                          signature, signature_length ),
343                         verify_status );
344         }
345     }
346 
347     if( usage & ( PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE ) )
348     {
349         unsigned char message[256] = "Hello, world...";
350         unsigned char signature[PSA_SIGNATURE_MAX_SIZE] = {0};
351         size_t message_length = 16;
352         size_t signature_length = sizeof( signature );
353 
354         if( usage & PSA_KEY_USAGE_SIGN_MESSAGE )
355         {
356             PSA_ASSERT( psa_sign_message( key, alg,
357                                           message, message_length,
358                                           signature, sizeof( signature ),
359                                           &signature_length ) );
360         }
361 
362         if( usage & PSA_KEY_USAGE_VERIFY_MESSAGE )
363         {
364             psa_status_t verify_status =
365                 ( usage & PSA_KEY_USAGE_SIGN_MESSAGE ?
366                   PSA_SUCCESS :
367                   PSA_ERROR_INVALID_SIGNATURE );
368             TEST_EQUAL( psa_verify_message( key, alg,
369                                             message, message_length,
370                                             signature, signature_length ),
371                         verify_status );
372         }
373     }
374 
375     return( 1 );
376 
377 exit:
378     return( 0 );
379 }
380 
exercise_asymmetric_encryption_key(mbedtls_svc_key_id_t key,psa_key_usage_t usage,psa_algorithm_t alg)381 static int exercise_asymmetric_encryption_key( mbedtls_svc_key_id_t key,
382                                                psa_key_usage_t usage,
383                                                psa_algorithm_t alg )
384 {
385     unsigned char plaintext[256] = "Hello, world...";
386     unsigned char ciphertext[256] = "(wabblewebblewibblewobblewubble)";
387     size_t ciphertext_length = sizeof( ciphertext );
388     size_t plaintext_length = 16;
389 
390     if( usage & PSA_KEY_USAGE_ENCRYPT )
391     {
392         PSA_ASSERT( psa_asymmetric_encrypt( key, alg,
393                                             plaintext, plaintext_length,
394                                             NULL, 0,
395                                             ciphertext, sizeof( ciphertext ),
396                                             &ciphertext_length ) );
397     }
398 
399     if( usage & PSA_KEY_USAGE_DECRYPT )
400     {
401         psa_status_t status =
402             psa_asymmetric_decrypt( key, alg,
403                                     ciphertext, ciphertext_length,
404                                     NULL, 0,
405                                     plaintext, sizeof( plaintext ),
406                                     &plaintext_length );
407         TEST_ASSERT( status == PSA_SUCCESS ||
408                      ( ( usage & PSA_KEY_USAGE_ENCRYPT ) == 0 &&
409                        ( status == PSA_ERROR_INVALID_ARGUMENT ||
410                          status == PSA_ERROR_INVALID_PADDING ) ) );
411     }
412 
413     return( 1 );
414 
415 exit:
416     return( 0 );
417 }
418 
mbedtls_test_psa_setup_key_derivation_wrap(psa_key_derivation_operation_t * operation,mbedtls_svc_key_id_t key,psa_algorithm_t alg,const unsigned char * input1,size_t input1_length,const unsigned char * input2,size_t input2_length,size_t capacity)419 int mbedtls_test_psa_setup_key_derivation_wrap(
420     psa_key_derivation_operation_t* operation,
421     mbedtls_svc_key_id_t key,
422     psa_algorithm_t alg,
423     const unsigned char* input1, size_t input1_length,
424     const unsigned char* input2, size_t input2_length,
425     size_t capacity )
426 {
427     PSA_ASSERT( psa_key_derivation_setup( operation, alg ) );
428     if( PSA_ALG_IS_HKDF( alg ) )
429     {
430         PSA_ASSERT( psa_key_derivation_input_bytes( operation,
431                                                     PSA_KEY_DERIVATION_INPUT_SALT,
432                                                     input1, input1_length ) );
433         PSA_ASSERT( psa_key_derivation_input_key( operation,
434                                                   PSA_KEY_DERIVATION_INPUT_SECRET,
435                                                   key ) );
436         PSA_ASSERT( psa_key_derivation_input_bytes( operation,
437                                                     PSA_KEY_DERIVATION_INPUT_INFO,
438                                                     input2,
439                                                     input2_length ) );
440     }
441     else if( PSA_ALG_IS_TLS12_PRF( alg ) ||
442              PSA_ALG_IS_TLS12_PSK_TO_MS( alg ) )
443     {
444         PSA_ASSERT( psa_key_derivation_input_bytes( operation,
445                                                     PSA_KEY_DERIVATION_INPUT_SEED,
446                                                     input1, input1_length ) );
447         PSA_ASSERT( psa_key_derivation_input_key( operation,
448                                                   PSA_KEY_DERIVATION_INPUT_SECRET,
449                                                   key ) );
450         PSA_ASSERT( psa_key_derivation_input_bytes( operation,
451                                                     PSA_KEY_DERIVATION_INPUT_LABEL,
452                                                     input2, input2_length ) );
453     }
454     else
455     {
456         TEST_ASSERT( ! "Key derivation algorithm not supported" );
457     }
458 
459     if( capacity != SIZE_MAX )
460         PSA_ASSERT( psa_key_derivation_set_capacity( operation, capacity ) );
461 
462     return( 1 );
463 
464 exit:
465     return( 0 );
466 }
467 
468 
exercise_key_derivation_key(mbedtls_svc_key_id_t key,psa_key_usage_t usage,psa_algorithm_t alg)469 static int exercise_key_derivation_key( mbedtls_svc_key_id_t key,
470                                         psa_key_usage_t usage,
471                                         psa_algorithm_t alg )
472 {
473     psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
474     unsigned char input1[] = "Input 1";
475     size_t input1_length = sizeof( input1 );
476     unsigned char input2[] = "Input 2";
477     size_t input2_length = sizeof( input2 );
478     unsigned char output[1];
479     size_t capacity = sizeof( output );
480 
481     if( usage & PSA_KEY_USAGE_DERIVE )
482     {
483         if( !mbedtls_test_psa_setup_key_derivation_wrap( &operation, key, alg,
484                                                          input1, input1_length,
485                                                          input2, input2_length,
486                                                          capacity ) )
487             goto exit;
488 
489         PSA_ASSERT( psa_key_derivation_output_bytes( &operation,
490                                                      output,
491                                                      capacity ) );
492         PSA_ASSERT( psa_key_derivation_abort( &operation ) );
493     }
494 
495     return( 1 );
496 
497 exit:
498     return( 0 );
499 }
500 
501 /* We need two keys to exercise key agreement. Exercise the
502  * private key against its own public key. */
mbedtls_test_psa_key_agreement_with_self(psa_key_derivation_operation_t * operation,mbedtls_svc_key_id_t key)503 psa_status_t mbedtls_test_psa_key_agreement_with_self(
504     psa_key_derivation_operation_t *operation,
505     mbedtls_svc_key_id_t key )
506 {
507     psa_key_type_t private_key_type;
508     psa_key_type_t public_key_type;
509     size_t key_bits;
510     uint8_t *public_key = NULL;
511     size_t public_key_length;
512     /* Return GENERIC_ERROR if something other than the final call to
513      * psa_key_derivation_key_agreement fails. This isn't fully satisfactory,
514      * but it's good enough: callers will report it as a failed test anyway. */
515     psa_status_t status = PSA_ERROR_GENERIC_ERROR;
516     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
517 
518     PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
519     private_key_type = psa_get_key_type( &attributes );
520     key_bits = psa_get_key_bits( &attributes );
521     public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR( private_key_type );
522     public_key_length = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( public_key_type, key_bits );
523     ASSERT_ALLOC( public_key, public_key_length );
524     PSA_ASSERT( psa_export_public_key( key, public_key, public_key_length,
525                                        &public_key_length ) );
526 
527     status = psa_key_derivation_key_agreement(
528         operation, PSA_KEY_DERIVATION_INPUT_SECRET, key,
529         public_key, public_key_length );
530 exit:
531     /*
532      * Key attributes may have been returned by psa_get_key_attributes()
533      * thus reset them as required.
534      */
535     psa_reset_key_attributes( &attributes );
536 
537     mbedtls_free( public_key );
538     return( status );
539 }
540 
541 /* We need two keys to exercise key agreement. Exercise the
542  * private key against its own public key. */
mbedtls_test_psa_raw_key_agreement_with_self(psa_algorithm_t alg,mbedtls_svc_key_id_t key)543 psa_status_t mbedtls_test_psa_raw_key_agreement_with_self(
544     psa_algorithm_t alg,
545     mbedtls_svc_key_id_t key )
546 {
547     psa_key_type_t private_key_type;
548     psa_key_type_t public_key_type;
549     size_t key_bits;
550     uint8_t *public_key = NULL;
551     size_t public_key_length;
552     uint8_t output[1024];
553     size_t output_length;
554     /* Return GENERIC_ERROR if something other than the final call to
555      * psa_key_derivation_key_agreement fails. This isn't fully satisfactory,
556      * but it's good enough: callers will report it as a failed test anyway. */
557     psa_status_t status = PSA_ERROR_GENERIC_ERROR;
558     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
559 
560     PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
561     private_key_type = psa_get_key_type( &attributes );
562     key_bits = psa_get_key_bits( &attributes );
563     public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR( private_key_type );
564     public_key_length = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( public_key_type, key_bits );
565     ASSERT_ALLOC( public_key, public_key_length );
566     PSA_ASSERT( psa_export_public_key( key,
567                                        public_key, public_key_length,
568                                        &public_key_length ) );
569 
570     status = psa_raw_key_agreement( alg, key,
571                                     public_key, public_key_length,
572                                     output, sizeof( output ), &output_length );
573     if ( status == PSA_SUCCESS )
574     {
575         TEST_ASSERT( output_length <=
576                      PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE( private_key_type,
577                                                         key_bits ) );
578         TEST_ASSERT( output_length <=
579                      PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE );
580     }
581 
582 exit:
583     /*
584      * Key attributes may have been returned by psa_get_key_attributes()
585      * thus reset them as required.
586      */
587     psa_reset_key_attributes( &attributes );
588 
589     mbedtls_free( public_key );
590     return( status );
591 }
592 
exercise_raw_key_agreement_key(mbedtls_svc_key_id_t key,psa_key_usage_t usage,psa_algorithm_t alg)593 static int exercise_raw_key_agreement_key( mbedtls_svc_key_id_t key,
594                                            psa_key_usage_t usage,
595                                            psa_algorithm_t alg )
596 {
597     int ok = 0;
598 
599     if( usage & PSA_KEY_USAGE_DERIVE )
600     {
601         /* We need two keys to exercise key agreement. Exercise the
602          * private key against its own public key. */
603         PSA_ASSERT( mbedtls_test_psa_raw_key_agreement_with_self( alg, key ) );
604     }
605     ok = 1;
606 
607 exit:
608     return( ok );
609 }
610 
exercise_key_agreement_key(mbedtls_svc_key_id_t key,psa_key_usage_t usage,psa_algorithm_t alg)611 static int exercise_key_agreement_key( mbedtls_svc_key_id_t key,
612                                        psa_key_usage_t usage,
613                                        psa_algorithm_t alg )
614 {
615     psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
616     unsigned char output[1];
617     int ok = 0;
618 
619     if( usage & PSA_KEY_USAGE_DERIVE )
620     {
621         /* We need two keys to exercise key agreement. Exercise the
622          * private key against its own public key. */
623         PSA_ASSERT( psa_key_derivation_setup( &operation, alg ) );
624         PSA_ASSERT( mbedtls_test_psa_key_agreement_with_self( &operation, key ) );
625         PSA_ASSERT( psa_key_derivation_output_bytes( &operation,
626                                                      output,
627                                                      sizeof( output ) ) );
628         PSA_ASSERT( psa_key_derivation_abort( &operation ) );
629     }
630     ok = 1;
631 
632 exit:
633     return( ok );
634 }
635 
mbedtls_test_psa_exported_key_sanity_check(psa_key_type_t type,size_t bits,const uint8_t * exported,size_t exported_length)636 int mbedtls_test_psa_exported_key_sanity_check(
637     psa_key_type_t type, size_t bits,
638     const uint8_t *exported, size_t exported_length )
639 {
640     TEST_ASSERT( exported_length <= PSA_EXPORT_KEY_OUTPUT_SIZE( type, bits ) );
641 
642     if( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) )
643         TEST_EQUAL( exported_length, PSA_BITS_TO_BYTES( bits ) );
644     else
645 
646 #if defined(MBEDTLS_ASN1_PARSE_C)
647     if( type == PSA_KEY_TYPE_RSA_KEY_PAIR )
648     {
649         uint8_t *p = (uint8_t*) exported;
650         const uint8_t *end = exported + exported_length;
651         size_t len;
652         /*   RSAPrivateKey ::= SEQUENCE {
653          *       version             INTEGER,  -- must be 0
654          *       modulus             INTEGER,  -- n
655          *       publicExponent      INTEGER,  -- e
656          *       privateExponent     INTEGER,  -- d
657          *       prime1              INTEGER,  -- p
658          *       prime2              INTEGER,  -- q
659          *       exponent1           INTEGER,  -- d mod (p-1)
660          *       exponent2           INTEGER,  -- d mod (q-1)
661          *       coefficient         INTEGER,  -- (inverse of q) mod p
662          *   }
663          */
664         TEST_EQUAL( mbedtls_asn1_get_tag( &p, end, &len,
665                                           MBEDTLS_ASN1_SEQUENCE |
666                                           MBEDTLS_ASN1_CONSTRUCTED ), 0 );
667         TEST_EQUAL( len, end - p );
668         if( ! mbedtls_test_asn1_skip_integer( &p, end, 0, 0, 0 ) )
669             goto exit;
670         if( ! mbedtls_test_asn1_skip_integer( &p, end, bits, bits, 1 ) )
671             goto exit;
672         if( ! mbedtls_test_asn1_skip_integer( &p, end, 2, bits, 1 ) )
673             goto exit;
674         /* Require d to be at least half the size of n. */
675         if( ! mbedtls_test_asn1_skip_integer( &p, end, bits / 2, bits, 1 ) )
676             goto exit;
677         /* Require p and q to be at most half the size of n, rounded up. */
678         if( ! mbedtls_test_asn1_skip_integer( &p, end, bits / 2, bits / 2 + 1, 1 ) )
679             goto exit;
680         if( ! mbedtls_test_asn1_skip_integer( &p, end, bits / 2, bits / 2 + 1, 1 ) )
681             goto exit;
682         if( ! mbedtls_test_asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
683             goto exit;
684         if( ! mbedtls_test_asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
685             goto exit;
686         if( ! mbedtls_test_asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
687             goto exit;
688         TEST_EQUAL( p - end, 0 );
689 
690         TEST_ASSERT( exported_length <= PSA_EXPORT_KEY_PAIR_MAX_SIZE );
691     }
692     else
693 #endif /* MBEDTLS_ASN1_PARSE_C */
694 
695 #if defined(MBEDTLS_ECP_C)
696     if( PSA_KEY_TYPE_IS_ECC_KEY_PAIR( type ) )
697     {
698         /* Just the secret value */
699         TEST_EQUAL( exported_length, PSA_BITS_TO_BYTES( bits ) );
700 
701         TEST_ASSERT( exported_length <= PSA_EXPORT_KEY_PAIR_MAX_SIZE );
702     }
703     else
704 #endif /* MBEDTLS_ECP_C */
705 
706 #if defined(MBEDTLS_ASN1_PARSE_C)
707     if( type == PSA_KEY_TYPE_RSA_PUBLIC_KEY )
708     {
709         uint8_t *p = (uint8_t*) exported;
710         const uint8_t *end = exported + exported_length;
711         size_t len;
712         /*   RSAPublicKey ::= SEQUENCE {
713          *      modulus            INTEGER,    -- n
714          *      publicExponent     INTEGER  }  -- e
715          */
716         TEST_EQUAL( mbedtls_asn1_get_tag( &p, end, &len,
717                                           MBEDTLS_ASN1_SEQUENCE |
718                                           MBEDTLS_ASN1_CONSTRUCTED ),
719                     0 );
720         TEST_EQUAL( len, end - p );
721         if( ! mbedtls_test_asn1_skip_integer( &p, end, bits, bits, 1 ) )
722             goto exit;
723         if( ! mbedtls_test_asn1_skip_integer( &p, end, 2, bits, 1 ) )
724             goto exit;
725         TEST_EQUAL( p - end, 0 );
726 
727 
728         TEST_ASSERT( exported_length <=
729                      PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( type, bits ) );
730         TEST_ASSERT( exported_length <=
731                      PSA_EXPORT_PUBLIC_KEY_MAX_SIZE );
732     }
733     else
734 #endif /* MBEDTLS_ASN1_PARSE_C */
735 
736 #if defined(MBEDTLS_ECP_C)
737     if( PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( type ) )
738     {
739 
740         TEST_ASSERT( exported_length <=
741                      PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( type, bits ) );
742         TEST_ASSERT( exported_length <=
743                      PSA_EXPORT_PUBLIC_KEY_MAX_SIZE );
744 
745         if( PSA_KEY_TYPE_ECC_GET_FAMILY( type ) == PSA_ECC_FAMILY_MONTGOMERY )
746         {
747             /* The representation of an ECC Montgomery public key is
748              * the raw compressed point */
749              TEST_EQUAL( PSA_BITS_TO_BYTES( bits ), exported_length );
750         }
751         else
752         {
753             /* The representation of an ECC Weierstrass public key is:
754              *      - The byte 0x04;
755              *      - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
756              *      - `y_P` as a `ceiling(m/8)`-byte string, big-endian;
757              *      - where m is the bit size associated with the curve.
758              */
759             TEST_EQUAL( 1 + 2 * PSA_BITS_TO_BYTES( bits ), exported_length );
760             TEST_EQUAL( exported[0], 4 );
761         }
762     }
763     else
764 #endif /* MBEDTLS_ECP_C */
765 
766     {
767         TEST_ASSERT( ! "Sanity check not implemented for this key type" );
768     }
769 
770 #if defined(MBEDTLS_DES_C)
771     if( type == PSA_KEY_TYPE_DES )
772     {
773         /* Check the parity bits. */
774         unsigned i;
775         for( i = 0; i < bits / 8; i++ )
776         {
777             unsigned bit_count = 0;
778             unsigned m;
779             for( m = 1; m <= 0x100; m <<= 1 )
780             {
781                 if( exported[i] & m )
782                     ++bit_count;
783             }
784             TEST_ASSERT( bit_count % 2 != 0 );
785         }
786     }
787 #endif
788 
789     return( 1 );
790 
791 exit:
792     return( 0 );
793 }
794 
exercise_export_key(mbedtls_svc_key_id_t key,psa_key_usage_t usage)795 static int exercise_export_key( mbedtls_svc_key_id_t key,
796                                 psa_key_usage_t usage )
797 {
798     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
799     uint8_t *exported = NULL;
800     size_t exported_size = 0;
801     size_t exported_length = 0;
802     int ok = 0;
803 
804     PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
805 
806     exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
807                         psa_get_key_type( &attributes ),
808                         psa_get_key_bits( &attributes ) );
809     ASSERT_ALLOC( exported, exported_size );
810 
811     if( ( usage & PSA_KEY_USAGE_EXPORT ) == 0 &&
812         ! PSA_KEY_TYPE_IS_PUBLIC_KEY( psa_get_key_type( &attributes ) ) )
813     {
814         TEST_EQUAL( psa_export_key( key, exported,
815                                     exported_size, &exported_length ),
816                     PSA_ERROR_NOT_PERMITTED );
817         ok = 1;
818         goto exit;
819     }
820 
821     PSA_ASSERT( psa_export_key( key,
822                                 exported, exported_size,
823                                 &exported_length ) );
824     ok = mbedtls_test_psa_exported_key_sanity_check(
825         psa_get_key_type( &attributes ), psa_get_key_bits( &attributes ),
826         exported, exported_length );
827 
828 exit:
829     /*
830      * Key attributes may have been returned by psa_get_key_attributes()
831      * thus reset them as required.
832      */
833     psa_reset_key_attributes( &attributes );
834 
835     mbedtls_free( exported );
836     return( ok );
837 }
838 
exercise_export_public_key(mbedtls_svc_key_id_t key)839 static int exercise_export_public_key( mbedtls_svc_key_id_t key )
840 {
841     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
842     psa_key_type_t public_type;
843     uint8_t *exported = NULL;
844     size_t exported_size = 0;
845     size_t exported_length = 0;
846     int ok = 0;
847 
848     PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
849     if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( psa_get_key_type( &attributes ) ) )
850     {
851         exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
852                             psa_get_key_type( &attributes ),
853                             psa_get_key_bits( &attributes ) );
854         ASSERT_ALLOC( exported, exported_size );
855 
856         TEST_EQUAL( psa_export_public_key( key, exported,
857                                            exported_size, &exported_length ),
858                     PSA_ERROR_INVALID_ARGUMENT );
859         ok = 1;
860         goto exit;
861     }
862 
863     public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(
864         psa_get_key_type( &attributes ) );
865     exported_size = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( public_type,
866                                                        psa_get_key_bits( &attributes ) );
867     ASSERT_ALLOC( exported, exported_size );
868 
869     PSA_ASSERT( psa_export_public_key( key,
870                                        exported, exported_size,
871                                        &exported_length ) );
872     ok = mbedtls_test_psa_exported_key_sanity_check(
873         public_type, psa_get_key_bits( &attributes ),
874         exported, exported_length );
875 
876 exit:
877     /*
878      * Key attributes may have been returned by psa_get_key_attributes()
879      * thus reset them as required.
880      */
881     psa_reset_key_attributes( &attributes );
882 
883     mbedtls_free( exported );
884     return( ok );
885 }
886 
mbedtls_test_psa_exercise_key(mbedtls_svc_key_id_t key,psa_key_usage_t usage,psa_algorithm_t alg)887 int mbedtls_test_psa_exercise_key( mbedtls_svc_key_id_t key,
888                                    psa_key_usage_t usage,
889                                    psa_algorithm_t alg )
890 {
891     int ok = 0;
892 
893     if( ! check_key_attributes_sanity( key ) )
894         return( 0 );
895 
896     if( alg == 0 )
897         ok = 1; /* If no algorihm, do nothing (used for raw data "keys"). */
898     else if( PSA_ALG_IS_MAC( alg ) )
899         ok = exercise_mac_key( key, usage, alg );
900     else if( PSA_ALG_IS_CIPHER( alg ) )
901         ok = exercise_cipher_key( key, usage, alg );
902     else if( PSA_ALG_IS_AEAD( alg ) )
903         ok = exercise_aead_key( key, usage, alg );
904     else if( PSA_ALG_IS_SIGN( alg ) )
905         ok = exercise_signature_key( key, usage, alg );
906     else if( PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) )
907         ok = exercise_asymmetric_encryption_key( key, usage, alg );
908     else if( PSA_ALG_IS_KEY_DERIVATION( alg ) )
909         ok = exercise_key_derivation_key( key, usage, alg );
910     else if( PSA_ALG_IS_RAW_KEY_AGREEMENT( alg ) )
911         ok = exercise_raw_key_agreement_key( key, usage, alg );
912     else if( PSA_ALG_IS_KEY_AGREEMENT( alg ) )
913         ok = exercise_key_agreement_key( key, usage, alg );
914     else
915         TEST_ASSERT( ! "No code to exercise this category of algorithm" );
916 
917     ok = ok && exercise_export_key( key, usage );
918     ok = ok && exercise_export_public_key( key );
919 
920 exit:
921     return( ok );
922 }
923 
mbedtls_test_psa_usage_to_exercise(psa_key_type_t type,psa_algorithm_t alg)924 psa_key_usage_t mbedtls_test_psa_usage_to_exercise( psa_key_type_t type,
925                                                     psa_algorithm_t alg )
926 {
927     if( PSA_ALG_IS_MAC( alg ) || PSA_ALG_IS_SIGN( alg ) )
928     {
929         if( PSA_ALG_IS_SIGN_HASH( alg ) )
930         {
931             if( PSA_ALG_SIGN_GET_HASH( alg ) )
932                 return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
933                         PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:
934                         PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH |
935                         PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE );
936         }
937         else if( PSA_ALG_IS_SIGN_MESSAGE( alg) )
938             return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
939                     PSA_KEY_USAGE_VERIFY_MESSAGE :
940                     PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE );
941 
942         return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
943                 PSA_KEY_USAGE_VERIFY_HASH :
944                 PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH );
945     }
946     else if( PSA_ALG_IS_CIPHER( alg ) || PSA_ALG_IS_AEAD( alg ) ||
947              PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) )
948     {
949         return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
950                 PSA_KEY_USAGE_ENCRYPT :
951                 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
952     }
953     else if( PSA_ALG_IS_KEY_DERIVATION( alg ) ||
954              PSA_ALG_IS_KEY_AGREEMENT( alg ) )
955     {
956         return( PSA_KEY_USAGE_DERIVE );
957     }
958     else
959     {
960         return( 0 );
961     }
962 
963 }
964 
965 #endif /* MBEDTLS_PSA_CRYPTO_C */
966