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