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         PSA_ALG_IS_SIGN_HASH(alg)) {
288         unsigned char payload[PSA_HASH_MAX_SIZE] = { 1 };
289         size_t payload_length = 16;
290         unsigned char signature[PSA_SIGNATURE_MAX_SIZE] = { 0 };
291         size_t signature_length = sizeof(signature);
292         psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);
293 
294         /* If the policy allows signing with any hash, just pick one. */
295         if (PSA_ALG_IS_SIGN_HASH(alg) && hash_alg == PSA_ALG_ANY_HASH) {
296     #if defined(KNOWN_SUPPORTED_HASH_ALG)
297             hash_alg = KNOWN_SUPPORTED_HASH_ALG;
298             alg ^= PSA_ALG_ANY_HASH ^ hash_alg;
299     #else
300             TEST_FAIL("No hash algorithm for hash-and-sign testing");
301     #endif
302         }
303 
304         /* Some algorithms require the payload to have the size of
305          * the hash encoded in the algorithm. Use this input size
306          * even for algorithms that allow other input sizes. */
307         if (hash_alg != 0) {
308             payload_length = PSA_HASH_LENGTH(hash_alg);
309         }
310 
311         if (usage & PSA_KEY_USAGE_SIGN_HASH) {
312             PSA_ASSERT(psa_sign_hash(key, alg,
313                                      payload, payload_length,
314                                      signature, sizeof(signature),
315                                      &signature_length));
316         }
317 
318         if (usage & PSA_KEY_USAGE_VERIFY_HASH) {
319             psa_status_t verify_status =
320                 (usage & PSA_KEY_USAGE_SIGN_HASH ?
321                  PSA_SUCCESS :
322                  PSA_ERROR_INVALID_SIGNATURE);
323             TEST_EQUAL(psa_verify_hash(key, alg,
324                                        payload, payload_length,
325                                        signature, signature_length),
326                        verify_status);
327         }
328     }
329 
330     if (can_sign_or_verify_message(usage, alg)) {
331         unsigned char message[256] = "Hello, world...";
332         unsigned char signature[PSA_SIGNATURE_MAX_SIZE] = { 0 };
333         size_t message_length = 16;
334         size_t signature_length = sizeof(signature);
335 
336         if (usage & PSA_KEY_USAGE_SIGN_MESSAGE) {
337             PSA_ASSERT(psa_sign_message(key, alg,
338                                         message, message_length,
339                                         signature, sizeof(signature),
340                                         &signature_length));
341         }
342 
343         if (usage & PSA_KEY_USAGE_VERIFY_MESSAGE) {
344             psa_status_t verify_status =
345                 (usage & PSA_KEY_USAGE_SIGN_MESSAGE ?
346                  PSA_SUCCESS :
347                  PSA_ERROR_INVALID_SIGNATURE);
348             TEST_EQUAL(psa_verify_message(key, alg,
349                                           message, message_length,
350                                           signature, signature_length),
351                        verify_status);
352         }
353     }
354 
355     return 1;
356 
357 exit:
358     return 0;
359 }
360 
exercise_asymmetric_encryption_key(mbedtls_svc_key_id_t key,psa_key_usage_t usage,psa_algorithm_t alg)361 static int exercise_asymmetric_encryption_key(mbedtls_svc_key_id_t key,
362                                               psa_key_usage_t usage,
363                                               psa_algorithm_t alg)
364 {
365     unsigned char plaintext[256] = "Hello, world...";
366     unsigned char ciphertext[256] = "(wabblewebblewibblewobblewubble)";
367     size_t ciphertext_length = sizeof(ciphertext);
368     size_t plaintext_length = 16;
369 
370     if (usage & PSA_KEY_USAGE_ENCRYPT) {
371         PSA_ASSERT(psa_asymmetric_encrypt(key, alg,
372                                           plaintext, plaintext_length,
373                                           NULL, 0,
374                                           ciphertext, sizeof(ciphertext),
375                                           &ciphertext_length));
376     }
377 
378     if (usage & PSA_KEY_USAGE_DECRYPT) {
379         psa_status_t status =
380             psa_asymmetric_decrypt(key, alg,
381                                    ciphertext, ciphertext_length,
382                                    NULL, 0,
383                                    plaintext, sizeof(plaintext),
384                                    &plaintext_length);
385         TEST_ASSERT(status == PSA_SUCCESS ||
386                     ((usage & PSA_KEY_USAGE_ENCRYPT) == 0 &&
387                      (status == PSA_ERROR_INVALID_ARGUMENT ||
388                       status == PSA_ERROR_INVALID_PADDING)));
389     }
390 
391     return 1;
392 
393 exit:
394     return 0;
395 }
396 
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)397 int mbedtls_test_psa_setup_key_derivation_wrap(
398     psa_key_derivation_operation_t *operation,
399     mbedtls_svc_key_id_t key,
400     psa_algorithm_t alg,
401     const unsigned char *input1, size_t input1_length,
402     const unsigned char *input2, size_t input2_length,
403     size_t capacity)
404 {
405     PSA_ASSERT(psa_key_derivation_setup(operation, alg));
406     if (PSA_ALG_IS_HKDF(alg)) {
407         PSA_ASSERT(psa_key_derivation_input_bytes(operation,
408                                                   PSA_KEY_DERIVATION_INPUT_SALT,
409                                                   input1, input1_length));
410         PSA_ASSERT(psa_key_derivation_input_key(operation,
411                                                 PSA_KEY_DERIVATION_INPUT_SECRET,
412                                                 key));
413         PSA_ASSERT(psa_key_derivation_input_bytes(operation,
414                                                   PSA_KEY_DERIVATION_INPUT_INFO,
415                                                   input2,
416                                                   input2_length));
417     } else if (PSA_ALG_IS_TLS12_PRF(alg) ||
418                PSA_ALG_IS_TLS12_PSK_TO_MS(alg)) {
419         PSA_ASSERT(psa_key_derivation_input_bytes(operation,
420                                                   PSA_KEY_DERIVATION_INPUT_SEED,
421                                                   input1, input1_length));
422         PSA_ASSERT(psa_key_derivation_input_key(operation,
423                                                 PSA_KEY_DERIVATION_INPUT_SECRET,
424                                                 key));
425         PSA_ASSERT(psa_key_derivation_input_bytes(operation,
426                                                   PSA_KEY_DERIVATION_INPUT_LABEL,
427                                                   input2, input2_length));
428     } else if (PSA_ALG_IS_PBKDF2(alg)) {
429         PSA_ASSERT(psa_key_derivation_input_integer(operation,
430                                                     PSA_KEY_DERIVATION_INPUT_COST,
431                                                     1U));
432         PSA_ASSERT(psa_key_derivation_input_bytes(operation,
433                                                   PSA_KEY_DERIVATION_INPUT_SALT,
434                                                   input2,
435                                                   input2_length));
436         PSA_ASSERT(psa_key_derivation_input_key(operation,
437                                                 PSA_KEY_DERIVATION_INPUT_PASSWORD,
438                                                 key));
439     } else {
440         TEST_FAIL("Key derivation algorithm not supported");
441     }
442 
443     if (capacity != SIZE_MAX) {
444         PSA_ASSERT(psa_key_derivation_set_capacity(operation, capacity));
445     }
446 
447     return 1;
448 
449 exit:
450     return 0;
451 }
452 
453 
exercise_key_derivation_key(mbedtls_svc_key_id_t key,psa_key_usage_t usage,psa_algorithm_t alg)454 static int exercise_key_derivation_key(mbedtls_svc_key_id_t key,
455                                        psa_key_usage_t usage,
456                                        psa_algorithm_t alg)
457 {
458     psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
459     unsigned char input1[] = "Input 1";
460     size_t input1_length = sizeof(input1);
461     unsigned char input2[] = "Input 2";
462     size_t input2_length = sizeof(input2);
463     unsigned char output[1];
464     size_t capacity = sizeof(output);
465 
466     if (usage & PSA_KEY_USAGE_DERIVE) {
467         if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, key, alg,
468                                                         input1, input1_length,
469                                                         input2, input2_length,
470                                                         capacity)) {
471             goto exit;
472         }
473 
474         PSA_ASSERT(psa_key_derivation_output_bytes(&operation,
475                                                    output,
476                                                    capacity));
477         PSA_ASSERT(psa_key_derivation_abort(&operation));
478     }
479 
480     return 1;
481 
482 exit:
483     return 0;
484 }
485 
486 /* We need two keys to exercise key agreement. Exercise the
487  * 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)488 psa_status_t mbedtls_test_psa_key_agreement_with_self(
489     psa_key_derivation_operation_t *operation,
490     mbedtls_svc_key_id_t key)
491 {
492     psa_key_type_t private_key_type;
493     psa_key_type_t public_key_type;
494     size_t key_bits;
495     uint8_t *public_key = NULL;
496     size_t public_key_length;
497     /* Return GENERIC_ERROR if something other than the final call to
498      * psa_key_derivation_key_agreement fails. This isn't fully satisfactory,
499      * but it's good enough: callers will report it as a failed test anyway. */
500     psa_status_t status = PSA_ERROR_GENERIC_ERROR;
501     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
502 
503     PSA_ASSERT(psa_get_key_attributes(key, &attributes));
504     private_key_type = psa_get_key_type(&attributes);
505     key_bits = psa_get_key_bits(&attributes);
506     public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(private_key_type);
507     public_key_length = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(public_key_type, key_bits);
508     TEST_CALLOC(public_key, public_key_length);
509     PSA_ASSERT(psa_export_public_key(key, public_key, public_key_length,
510                                      &public_key_length));
511 
512     status = psa_key_derivation_key_agreement(
513         operation, PSA_KEY_DERIVATION_INPUT_SECRET, key,
514         public_key, public_key_length);
515 exit:
516     /*
517      * Key attributes may have been returned by psa_get_key_attributes()
518      * thus reset them as required.
519      */
520     psa_reset_key_attributes(&attributes);
521 
522     mbedtls_free(public_key);
523     return status;
524 }
525 
526 /* We need two keys to exercise key agreement. Exercise the
527  * 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)528 psa_status_t mbedtls_test_psa_raw_key_agreement_with_self(
529     psa_algorithm_t alg,
530     mbedtls_svc_key_id_t key)
531 {
532     psa_key_type_t private_key_type;
533     psa_key_type_t public_key_type;
534     size_t key_bits;
535     uint8_t *public_key = NULL;
536     size_t public_key_length;
537     uint8_t output[1024];
538     size_t output_length;
539     /* Return GENERIC_ERROR if something other than the final call to
540      * psa_key_derivation_key_agreement fails. This isn't fully satisfactory,
541      * but it's good enough: callers will report it as a failed test anyway. */
542     psa_status_t status = PSA_ERROR_GENERIC_ERROR;
543     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
544 
545     PSA_ASSERT(psa_get_key_attributes(key, &attributes));
546     private_key_type = psa_get_key_type(&attributes);
547     key_bits = psa_get_key_bits(&attributes);
548     public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(private_key_type);
549     public_key_length = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(public_key_type, key_bits);
550     TEST_CALLOC(public_key, public_key_length);
551     PSA_ASSERT(psa_export_public_key(key,
552                                      public_key, public_key_length,
553                                      &public_key_length));
554 
555     status = psa_raw_key_agreement(alg, key,
556                                    public_key, public_key_length,
557                                    output, sizeof(output), &output_length);
558     if (status == PSA_SUCCESS) {
559         TEST_ASSERT(output_length <=
560                     PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(private_key_type,
561                                                       key_bits));
562         TEST_ASSERT(output_length <=
563                     PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE);
564     }
565 
566 exit:
567     /*
568      * Key attributes may have been returned by psa_get_key_attributes()
569      * thus reset them as required.
570      */
571     psa_reset_key_attributes(&attributes);
572 
573     mbedtls_free(public_key);
574     return status;
575 }
576 
exercise_raw_key_agreement_key(mbedtls_svc_key_id_t key,psa_key_usage_t usage,psa_algorithm_t alg)577 static int exercise_raw_key_agreement_key(mbedtls_svc_key_id_t key,
578                                           psa_key_usage_t usage,
579                                           psa_algorithm_t alg)
580 {
581     int ok = 0;
582 
583     if (usage & PSA_KEY_USAGE_DERIVE) {
584         /* We need two keys to exercise key agreement. Exercise the
585          * private key against its own public key. */
586         PSA_ASSERT(mbedtls_test_psa_raw_key_agreement_with_self(alg, key));
587     }
588     ok = 1;
589 
590 exit:
591     return ok;
592 }
593 
exercise_key_agreement_key(mbedtls_svc_key_id_t key,psa_key_usage_t usage,psa_algorithm_t alg)594 static int exercise_key_agreement_key(mbedtls_svc_key_id_t key,
595                                       psa_key_usage_t usage,
596                                       psa_algorithm_t alg)
597 {
598     psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
599     unsigned char input[1] = { 0 };
600     unsigned char output[1];
601     int ok = 0;
602     psa_algorithm_t kdf_alg = PSA_ALG_KEY_AGREEMENT_GET_KDF(alg);
603     psa_status_t expected_key_agreement_status = PSA_SUCCESS;
604 
605     if (usage & PSA_KEY_USAGE_DERIVE) {
606         /* We need two keys to exercise key agreement. Exercise the
607          * private key against its own public key. */
608         PSA_ASSERT(psa_key_derivation_setup(&operation, alg));
609         if (PSA_ALG_IS_TLS12_PRF(kdf_alg) ||
610             PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) {
611             PSA_ASSERT(psa_key_derivation_input_bytes(
612                            &operation, PSA_KEY_DERIVATION_INPUT_SEED,
613                            input, sizeof(input)));
614         }
615 
616         if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) {
617             PSA_ASSERT(psa_key_derivation_input_bytes(
618                            &operation, PSA_KEY_DERIVATION_INPUT_SALT,
619                            input, sizeof(input)));
620         }
621 
622         /* For HKDF_EXPAND input secret may fail as secret size may not match
623            to expected PRK size. In practice it means that key bits must match
624            hash length. Otherwise test should fail with INVALID_ARGUMENT. */
625         if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) {
626             psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
627             PSA_ASSERT(psa_get_key_attributes(key, &attributes));
628             size_t key_bits = psa_get_key_bits(&attributes);
629             psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(kdf_alg);
630 
631             if (PSA_BITS_TO_BYTES(key_bits) != PSA_HASH_LENGTH(hash_alg)) {
632                 expected_key_agreement_status = PSA_ERROR_INVALID_ARGUMENT;
633             }
634         }
635 
636         TEST_EQUAL(mbedtls_test_psa_key_agreement_with_self(&operation, key),
637                    expected_key_agreement_status);
638 
639         if (expected_key_agreement_status != PSA_SUCCESS) {
640             return 1;
641         }
642 
643         if (PSA_ALG_IS_TLS12_PRF(kdf_alg) ||
644             PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) {
645             PSA_ASSERT(psa_key_derivation_input_bytes(
646                            &operation, PSA_KEY_DERIVATION_INPUT_LABEL,
647                            input, sizeof(input)));
648         } else if (PSA_ALG_IS_HKDF(kdf_alg) || PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) {
649             PSA_ASSERT(psa_key_derivation_input_bytes(
650                            &operation, PSA_KEY_DERIVATION_INPUT_INFO,
651                            input, sizeof(input)));
652         }
653         PSA_ASSERT(psa_key_derivation_output_bytes(&operation,
654                                                    output,
655                                                    sizeof(output)));
656         PSA_ASSERT(psa_key_derivation_abort(&operation));
657     }
658     ok = 1;
659 
660 exit:
661     return ok;
662 }
663 
mbedtls_test_psa_exported_key_sanity_check(psa_key_type_t type,size_t bits,const uint8_t * exported,size_t exported_length)664 int mbedtls_test_psa_exported_key_sanity_check(
665     psa_key_type_t type, size_t bits,
666     const uint8_t *exported, size_t exported_length)
667 {
668     TEST_ASSERT(exported_length <= PSA_EXPORT_KEY_OUTPUT_SIZE(type, bits));
669 
670     if (PSA_KEY_TYPE_IS_UNSTRUCTURED(type)) {
671         TEST_EQUAL(exported_length, PSA_BITS_TO_BYTES(bits));
672     } else
673 
674 #if defined(MBEDTLS_ASN1_PARSE_C)
675     if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
676         uint8_t *p = (uint8_t *) exported;
677         const uint8_t *end = exported + exported_length;
678         size_t len;
679         /*   RSAPrivateKey ::= SEQUENCE {
680          *       version             INTEGER,  -- must be 0
681          *       modulus             INTEGER,  -- n
682          *       publicExponent      INTEGER,  -- e
683          *       privateExponent     INTEGER,  -- d
684          *       prime1              INTEGER,  -- p
685          *       prime2              INTEGER,  -- q
686          *       exponent1           INTEGER,  -- d mod (p-1)
687          *       exponent2           INTEGER,  -- d mod (q-1)
688          *       coefficient         INTEGER,  -- (inverse of q) mod p
689          *   }
690          */
691         TEST_EQUAL(mbedtls_asn1_get_tag(&p, end, &len,
692                                         MBEDTLS_ASN1_SEQUENCE |
693                                         MBEDTLS_ASN1_CONSTRUCTED), 0);
694         TEST_EQUAL(len, end - p);
695         if (!mbedtls_test_asn1_skip_integer(&p, end, 0, 0, 0)) {
696             goto exit;
697         }
698         if (!mbedtls_test_asn1_skip_integer(&p, end, bits, bits, 1)) {
699             goto exit;
700         }
701         if (!mbedtls_test_asn1_skip_integer(&p, end, 2, bits, 1)) {
702             goto exit;
703         }
704         /* Require d to be at least half the size of n. */
705         if (!mbedtls_test_asn1_skip_integer(&p, end, bits / 2, bits, 1)) {
706             goto exit;
707         }
708         /* Require p and q to be at most half the size of n, rounded up. */
709         if (!mbedtls_test_asn1_skip_integer(&p, end, bits / 2, bits / 2 + 1, 1)) {
710             goto exit;
711         }
712         if (!mbedtls_test_asn1_skip_integer(&p, end, bits / 2, bits / 2 + 1, 1)) {
713             goto exit;
714         }
715         if (!mbedtls_test_asn1_skip_integer(&p, end, 1, bits / 2 + 1, 0)) {
716             goto exit;
717         }
718         if (!mbedtls_test_asn1_skip_integer(&p, end, 1, bits / 2 + 1, 0)) {
719             goto exit;
720         }
721         if (!mbedtls_test_asn1_skip_integer(&p, end, 1, bits / 2 + 1, 0)) {
722             goto exit;
723         }
724         TEST_EQUAL(p - end, 0);
725 
726         TEST_ASSERT(exported_length <= PSA_EXPORT_KEY_PAIR_MAX_SIZE);
727     } else
728 #endif /* MBEDTLS_ASN1_PARSE_C */
729 
730     if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) {
731         /* Just the secret value */
732         TEST_EQUAL(exported_length, PSA_BITS_TO_BYTES(bits));
733 
734         TEST_ASSERT(exported_length <= PSA_EXPORT_KEY_PAIR_MAX_SIZE);
735     } else
736 
737 #if defined(MBEDTLS_ASN1_PARSE_C)
738     if (type == PSA_KEY_TYPE_RSA_PUBLIC_KEY) {
739         uint8_t *p = (uint8_t *) exported;
740         const uint8_t *end = exported + exported_length;
741         size_t len;
742         /*   RSAPublicKey ::= SEQUENCE {
743          *      modulus            INTEGER,    -- n
744          *      publicExponent     INTEGER  }  -- e
745          */
746         TEST_EQUAL(mbedtls_asn1_get_tag(&p, end, &len,
747                                         MBEDTLS_ASN1_SEQUENCE |
748                                         MBEDTLS_ASN1_CONSTRUCTED),
749                    0);
750         TEST_EQUAL(len, end - p);
751         if (!mbedtls_test_asn1_skip_integer(&p, end, bits, bits, 1)) {
752             goto exit;
753         }
754         if (!mbedtls_test_asn1_skip_integer(&p, end, 2, bits, 1)) {
755             goto exit;
756         }
757         TEST_EQUAL(p - end, 0);
758 
759 
760         TEST_ASSERT(exported_length <=
761                     PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(type, bits));
762         TEST_ASSERT(exported_length <=
763                     PSA_EXPORT_PUBLIC_KEY_MAX_SIZE);
764     } else
765 #endif /* MBEDTLS_ASN1_PARSE_C */
766 
767     if (PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type)) {
768 
769         TEST_ASSERT(exported_length <=
770                     PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(type, bits));
771         TEST_ASSERT(exported_length <=
772                     PSA_EXPORT_PUBLIC_KEY_MAX_SIZE);
773 
774         if (PSA_KEY_TYPE_ECC_GET_FAMILY(type) == PSA_ECC_FAMILY_MONTGOMERY) {
775             /* The representation of an ECC Montgomery public key is
776              * the raw compressed point */
777             TEST_EQUAL(PSA_BITS_TO_BYTES(bits), exported_length);
778         } else if (PSA_KEY_TYPE_ECC_GET_FAMILY(type) == PSA_ECC_FAMILY_TWISTED_EDWARDS) {
779             /* The representation of an ECC Edwards public key is
780              * the raw compressed point */
781             TEST_EQUAL(PSA_BITS_TO_BYTES(bits + 1), exported_length);
782         } else {
783             /* The representation of an ECC Weierstrass public key is:
784              *      - The byte 0x04;
785              *      - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
786              *      - `y_P` as a `ceiling(m/8)`-byte string, big-endian;
787              *      - where m is the bit size associated with the curve.
788              */
789             TEST_EQUAL(1 + 2 * PSA_BITS_TO_BYTES(bits), exported_length);
790             TEST_EQUAL(exported[0], 4);
791         }
792     } else
793     if (PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(type) || PSA_KEY_TYPE_IS_DH_KEY_PAIR(type)) {
794         TEST_ASSERT(exported_length ==
795                     PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(type, bits));
796         TEST_ASSERT(exported_length <=
797                     PSA_EXPORT_PUBLIC_KEY_MAX_SIZE);
798     } else {
799         (void) exported;
800         TEST_FAIL("Sanity check not implemented for this key type");
801     }
802 
803 #if defined(MBEDTLS_DES_C)
804     if (type == PSA_KEY_TYPE_DES) {
805         /* Check the parity bits. */
806         unsigned i;
807         for (i = 0; i < bits / 8; i++) {
808             unsigned bit_count = 0;
809             unsigned m;
810             for (m = 1; m <= 0x100; m <<= 1) {
811                 if (exported[i] & m) {
812                     ++bit_count;
813                 }
814             }
815             TEST_ASSERT(bit_count % 2 != 0);
816         }
817     }
818 #endif
819 
820     return 1;
821 
822 exit:
823     return 0;
824 }
825 
exercise_export_key(mbedtls_svc_key_id_t key,psa_key_usage_t usage)826 static int exercise_export_key(mbedtls_svc_key_id_t key,
827                                psa_key_usage_t usage)
828 {
829     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
830     uint8_t *exported = NULL;
831     size_t exported_size = 0;
832     size_t exported_length = 0;
833     int ok = 0;
834 
835     PSA_ASSERT(psa_get_key_attributes(key, &attributes));
836 
837     exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
838         psa_get_key_type(&attributes),
839         psa_get_key_bits(&attributes));
840     TEST_CALLOC(exported, exported_size);
841 
842     if ((usage & PSA_KEY_USAGE_EXPORT) == 0 &&
843         !PSA_KEY_TYPE_IS_PUBLIC_KEY(psa_get_key_type(&attributes))) {
844         TEST_EQUAL(psa_export_key(key, exported,
845                                   exported_size, &exported_length),
846                    PSA_ERROR_NOT_PERMITTED);
847         ok = 1;
848         goto exit;
849     }
850 
851     PSA_ASSERT(psa_export_key(key,
852                               exported, exported_size,
853                               &exported_length));
854     ok = mbedtls_test_psa_exported_key_sanity_check(
855         psa_get_key_type(&attributes), psa_get_key_bits(&attributes),
856         exported, exported_length);
857 
858 exit:
859     /*
860      * Key attributes may have been returned by psa_get_key_attributes()
861      * thus reset them as required.
862      */
863     psa_reset_key_attributes(&attributes);
864 
865     mbedtls_free(exported);
866     return ok;
867 }
868 
exercise_export_public_key(mbedtls_svc_key_id_t key)869 static int exercise_export_public_key(mbedtls_svc_key_id_t key)
870 {
871     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
872     psa_key_type_t public_type;
873     uint8_t *exported = NULL;
874     size_t exported_size = 0;
875     size_t exported_length = 0;
876     int ok = 0;
877 
878     PSA_ASSERT(psa_get_key_attributes(key, &attributes));
879     if (!PSA_KEY_TYPE_IS_ASYMMETRIC(psa_get_key_type(&attributes))) {
880         exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
881             psa_get_key_type(&attributes),
882             psa_get_key_bits(&attributes));
883         TEST_CALLOC(exported, exported_size);
884 
885         TEST_EQUAL(psa_export_public_key(key, exported,
886                                          exported_size, &exported_length),
887                    PSA_ERROR_INVALID_ARGUMENT);
888         ok = 1;
889         goto exit;
890     }
891 
892     public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(
893         psa_get_key_type(&attributes));
894     exported_size = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(public_type,
895                                                       psa_get_key_bits(&attributes));
896     TEST_CALLOC(exported, exported_size);
897 
898     PSA_ASSERT(psa_export_public_key(key,
899                                      exported, exported_size,
900                                      &exported_length));
901     ok = mbedtls_test_psa_exported_key_sanity_check(
902         public_type, psa_get_key_bits(&attributes),
903         exported, exported_length);
904 
905 exit:
906     /*
907      * Key attributes may have been returned by psa_get_key_attributes()
908      * thus reset them as required.
909      */
910     psa_reset_key_attributes(&attributes);
911 
912     mbedtls_free(exported);
913     return ok;
914 }
915 
mbedtls_test_psa_exercise_key(mbedtls_svc_key_id_t key,psa_key_usage_t usage,psa_algorithm_t alg)916 int mbedtls_test_psa_exercise_key(mbedtls_svc_key_id_t key,
917                                   psa_key_usage_t usage,
918                                   psa_algorithm_t alg)
919 {
920     int ok = 0;
921 
922     if (!check_key_attributes_sanity(key)) {
923         return 0;
924     }
925 
926     if (alg == 0) {
927         ok = 1; /* If no algorithm, do nothing (used for raw data "keys"). */
928     } else if (PSA_ALG_IS_MAC(alg)) {
929         ok = exercise_mac_key(key, usage, alg);
930     } else if (PSA_ALG_IS_CIPHER(alg)) {
931         ok = exercise_cipher_key(key, usage, alg);
932     } else if (PSA_ALG_IS_AEAD(alg)) {
933         ok = exercise_aead_key(key, usage, alg);
934     } else if (PSA_ALG_IS_SIGN(alg)) {
935         ok = exercise_signature_key(key, usage, alg);
936     } else if (PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg)) {
937         ok = exercise_asymmetric_encryption_key(key, usage, alg);
938     } else if (PSA_ALG_IS_KEY_DERIVATION(alg)) {
939         ok = exercise_key_derivation_key(key, usage, alg);
940     } else if (PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) {
941         ok = exercise_raw_key_agreement_key(key, usage, alg);
942     } else if (PSA_ALG_IS_KEY_AGREEMENT(alg)) {
943         ok = exercise_key_agreement_key(key, usage, alg);
944     } else {
945         TEST_FAIL("No code to exercise this category of algorithm");
946     }
947 
948     ok = ok && exercise_export_key(key, usage);
949     ok = ok && exercise_export_public_key(key);
950 
951 exit:
952     return ok;
953 }
954 
mbedtls_test_psa_usage_to_exercise(psa_key_type_t type,psa_algorithm_t alg)955 psa_key_usage_t mbedtls_test_psa_usage_to_exercise(psa_key_type_t type,
956                                                    psa_algorithm_t alg)
957 {
958     if (PSA_ALG_IS_MAC(alg) || PSA_ALG_IS_SIGN(alg)) {
959         if (PSA_ALG_IS_SIGN_HASH(alg)) {
960             if (PSA_ALG_SIGN_GET_HASH(alg)) {
961                 return PSA_KEY_TYPE_IS_PUBLIC_KEY(type) ?
962                        PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE :
963                        PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH |
964                        PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE;
965             }
966         } else if (PSA_ALG_IS_SIGN_MESSAGE(alg)) {
967             return PSA_KEY_TYPE_IS_PUBLIC_KEY(type) ?
968                    PSA_KEY_USAGE_VERIFY_MESSAGE :
969                    PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE;
970         }
971 
972         return PSA_KEY_TYPE_IS_PUBLIC_KEY(type) ?
973                PSA_KEY_USAGE_VERIFY_HASH :
974                PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH;
975     } else if (PSA_ALG_IS_CIPHER(alg) || PSA_ALG_IS_AEAD(alg) ||
976                PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg)) {
977         return PSA_KEY_TYPE_IS_PUBLIC_KEY(type) ?
978                PSA_KEY_USAGE_ENCRYPT :
979                PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT;
980     } else if (PSA_ALG_IS_KEY_DERIVATION(alg) ||
981                PSA_ALG_IS_KEY_AGREEMENT(alg)) {
982         return PSA_KEY_USAGE_DERIVE;
983     } else {
984         return 0;
985     }
986 
987 }
988 
989 #endif /* MBEDTLS_PSA_CRYPTO_C */
990