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_PK_C)
24#include <pk_internal.h>
25#endif
26#if defined(MBEDTLS_ECP_C)
27#include <mbedtls/ecp.h>
28#endif
29#if defined(MBEDTLS_RSA_C)
30#include <rsa_internal.h>
31#endif
32
33#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
34static int lifetime_is_dynamic_secure_element(psa_key_lifetime_t lifetime)
35{
36    return PSA_KEY_LIFETIME_GET_LOCATION(lifetime) !=
37           PSA_KEY_LOCATION_LOCAL_STORAGE;
38}
39#endif
40
41static int check_key_attributes_sanity(mbedtls_svc_key_id_t key,
42                                       int key_destroyable)
43{
44    int ok = 0;
45    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
46    psa_key_lifetime_t lifetime;
47    mbedtls_svc_key_id_t id;
48    psa_key_type_t type;
49    size_t bits;
50    psa_status_t status = psa_get_key_attributes(key, &attributes);
51    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
52        /* The key has been destroyed. */
53        psa_reset_key_attributes(&attributes);
54        return 1;
55    }
56    PSA_ASSERT(status);
57    lifetime = psa_get_key_lifetime(&attributes);
58    id = psa_get_key_id(&attributes);
59    type = psa_get_key_type(&attributes);
60    bits = psa_get_key_bits(&attributes);
61
62    /* Persistence */
63    if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) {
64        TEST_ASSERT(
65            (PSA_KEY_ID_VOLATILE_MIN <=
66             MBEDTLS_SVC_KEY_ID_GET_KEY_ID(id)) &&
67            (MBEDTLS_SVC_KEY_ID_GET_KEY_ID(id) <=
68             PSA_KEY_ID_VOLATILE_MAX));
69    } else {
70        TEST_ASSERT(
71            (PSA_KEY_ID_USER_MIN <= MBEDTLS_SVC_KEY_ID_GET_KEY_ID(id)) &&
72            (MBEDTLS_SVC_KEY_ID_GET_KEY_ID(id) <= PSA_KEY_ID_USER_MAX));
73    }
74#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
75    /* MBEDTLS_PSA_CRYPTO_SE_C does not support thread safety. */
76    if (key_destroyable == 0) {
77        /* randomly-generated 64-bit constant, should never appear in test data */
78        psa_key_slot_number_t slot_number = 0xec94d4a5058a1a21;
79        status = psa_get_key_slot_number(&attributes, &slot_number);
80        if (lifetime_is_dynamic_secure_element(lifetime)) {
81            /* Mbed TLS currently always exposes the slot number to
82             * applications. This is not mandated by the PSA specification
83             * and may change in future versions. */
84            TEST_EQUAL(status, 0);
85            TEST_ASSERT(slot_number != 0xec94d4a5058a1a21);
86        } else {
87            TEST_EQUAL(status, PSA_ERROR_INVALID_ARGUMENT);
88        }
89    }
90#endif
91
92    /* Type and size */
93    TEST_ASSERT(type != 0);
94    TEST_ASSERT(bits != 0);
95    TEST_ASSERT(bits <= PSA_MAX_KEY_BITS);
96    if (PSA_KEY_TYPE_IS_UNSTRUCTURED(type)) {
97        TEST_ASSERT(bits % 8 == 0);
98    }
99
100    /* MAX macros concerning specific key types */
101    if (PSA_KEY_TYPE_IS_ECC(type)) {
102        TEST_ASSERT(bits <= PSA_VENDOR_ECC_MAX_CURVE_BITS);
103    } else if (PSA_KEY_TYPE_IS_RSA(type)) {
104        TEST_ASSERT(bits <= PSA_VENDOR_RSA_MAX_KEY_BITS);
105    }
106    TEST_ASSERT(PSA_BLOCK_CIPHER_BLOCK_LENGTH(type) <= PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE);
107
108    ok = 1;
109
110exit:
111    /*
112     * Key attributes may have been returned by psa_get_key_attributes()
113     * thus reset them as required.
114     */
115    psa_reset_key_attributes(&attributes);
116
117    return ok;
118}
119
120static int exercise_mac_key(mbedtls_svc_key_id_t key,
121                            psa_key_usage_t usage,
122                            psa_algorithm_t alg,
123                            int key_destroyable)
124{
125    psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
126    const unsigned char input[] = "foo";
127    unsigned char mac[PSA_MAC_MAX_SIZE] = { 0 };
128    size_t mac_length = sizeof(mac);
129    psa_status_t status = PSA_SUCCESS;
130    /* Convert wildcard algorithm to exercisable algorithm */
131    if (alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) {
132        alg = PSA_ALG_TRUNCATED_MAC(alg, PSA_MAC_TRUNCATED_LENGTH(alg));
133    }
134
135    if (usage & PSA_KEY_USAGE_SIGN_HASH) {
136        status = psa_mac_sign_setup(&operation, key, alg);
137        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
138            /* The key has been destroyed. */
139            PSA_ASSERT(psa_mac_abort(&operation));
140            return 1;
141        }
142        PSA_ASSERT(status);
143        PSA_ASSERT(psa_mac_update(&operation,
144                                  input, sizeof(input)));
145        PSA_ASSERT(psa_mac_sign_finish(&operation,
146                                       mac, sizeof(mac),
147                                       &mac_length));
148    }
149
150    if (usage & PSA_KEY_USAGE_VERIFY_HASH) {
151        psa_status_t verify_status =
152            (usage & PSA_KEY_USAGE_SIGN_HASH ?
153             PSA_SUCCESS :
154             PSA_ERROR_INVALID_SIGNATURE);
155        status = psa_mac_verify_setup(&operation, key, alg);
156        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
157            /* The key has been destroyed. */
158            PSA_ASSERT(psa_mac_abort(&operation));
159            return 1;
160        }
161        PSA_ASSERT(status);
162        PSA_ASSERT(psa_mac_update(&operation,
163                                  input, sizeof(input)));
164        TEST_EQUAL(psa_mac_verify_finish(&operation, mac, mac_length),
165                   verify_status);
166    }
167
168    return 1;
169
170exit:
171    psa_mac_abort(&operation);
172    return 0;
173}
174
175static int exercise_cipher_key(mbedtls_svc_key_id_t key,
176                               psa_key_usage_t usage,
177                               psa_algorithm_t alg,
178                               int key_destroyable)
179{
180    psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
181    unsigned char iv[PSA_CIPHER_IV_MAX_SIZE] = { 0 };
182    size_t iv_length;
183    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
184    psa_key_type_t key_type;
185    const unsigned char plaintext[16] = "Hello, world...";
186    unsigned char ciphertext[32] = "(wabblewebblewibblewobblewubble)";
187    size_t ciphertext_length = sizeof(ciphertext);
188    unsigned char decrypted[sizeof(ciphertext)];
189    size_t part_length;
190    psa_status_t status = PSA_SUCCESS;
191
192    PSA_ASSERT(psa_get_key_attributes(key, &attributes));
193    key_type = psa_get_key_type(&attributes);
194    iv_length = PSA_CIPHER_IV_LENGTH(key_type, alg);
195
196    if (usage & PSA_KEY_USAGE_ENCRYPT) {
197        status = psa_cipher_encrypt_setup(&operation, key, alg);
198        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
199            /* The key has been destroyed. */
200            PSA_ASSERT(psa_cipher_abort(&operation));
201            return 1;
202        }
203        PSA_ASSERT(status);
204        if (iv_length != 0) {
205            PSA_ASSERT(psa_cipher_generate_iv(&operation,
206                                              iv, sizeof(iv),
207                                              &iv_length));
208        }
209        PSA_ASSERT(psa_cipher_update(&operation,
210                                     plaintext, sizeof(plaintext),
211                                     ciphertext, sizeof(ciphertext),
212                                     &ciphertext_length));
213        PSA_ASSERT(psa_cipher_finish(&operation,
214                                     ciphertext + ciphertext_length,
215                                     sizeof(ciphertext) - ciphertext_length,
216                                     &part_length));
217        ciphertext_length += part_length;
218    }
219
220    if (usage & PSA_KEY_USAGE_DECRYPT) {
221        int maybe_invalid_padding = 0;
222        if (!(usage & PSA_KEY_USAGE_ENCRYPT)) {
223            maybe_invalid_padding = !PSA_ALG_IS_STREAM_CIPHER(alg);
224        }
225        status = psa_cipher_decrypt_setup(&operation, key, alg);
226        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
227            /* The key has been destroyed. */
228            PSA_ASSERT(psa_cipher_abort(&operation));
229            return 1;
230        }
231        PSA_ASSERT(status);
232        if (iv_length != 0) {
233            PSA_ASSERT(psa_cipher_set_iv(&operation,
234                                         iv, iv_length));
235        }
236        PSA_ASSERT(psa_cipher_update(&operation,
237                                     ciphertext, ciphertext_length,
238                                     decrypted, sizeof(decrypted),
239                                     &part_length));
240        status = psa_cipher_finish(&operation,
241                                   decrypted + part_length,
242                                   sizeof(decrypted) - part_length,
243                                   &part_length);
244        /* For a stream cipher, all inputs are valid. For a block cipher,
245         * if the input is some arbitrary data rather than an actual
246           ciphertext, a padding error is likely.  */
247        if (maybe_invalid_padding) {
248            TEST_ASSERT(status == PSA_SUCCESS ||
249                        status == PSA_ERROR_INVALID_PADDING);
250        } else {
251            PSA_ASSERT(status);
252        }
253    }
254
255    return 1;
256
257exit:
258    psa_cipher_abort(&operation);
259    psa_reset_key_attributes(&attributes);
260    return 0;
261}
262
263static int exercise_aead_key(mbedtls_svc_key_id_t key,
264                             psa_key_usage_t usage,
265                             psa_algorithm_t alg,
266                             int key_destroyable)
267{
268    unsigned char nonce[PSA_AEAD_NONCE_MAX_SIZE] = { 0 };
269    size_t nonce_length;
270    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
271    psa_key_type_t key_type;
272    unsigned char plaintext[16] = "Hello, world...";
273    unsigned char ciphertext[48] = "(wabblewebblewibblewobblewubble)";
274    size_t ciphertext_length = sizeof(ciphertext);
275    size_t plaintext_length = sizeof(ciphertext);
276    psa_status_t status = PSA_SUCCESS;
277
278    /* Convert wildcard algorithm to exercisable algorithm */
279    if (alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) {
280        alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, PSA_ALG_AEAD_GET_TAG_LENGTH(alg));
281    }
282
283    PSA_ASSERT(psa_get_key_attributes(key, &attributes));
284    key_type = psa_get_key_type(&attributes);
285    nonce_length = PSA_AEAD_NONCE_LENGTH(key_type, alg);
286
287    if (usage & PSA_KEY_USAGE_ENCRYPT) {
288        status = psa_aead_encrypt(key, alg,
289                                  nonce, nonce_length,
290                                  NULL, 0,
291                                  plaintext, sizeof(plaintext),
292                                  ciphertext, sizeof(ciphertext),
293                                  &ciphertext_length);
294        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
295            /* The key has been destroyed. */
296            return 1;
297        }
298        PSA_ASSERT(status);
299    }
300
301    if (usage & PSA_KEY_USAGE_DECRYPT) {
302        psa_status_t verify_status =
303            (usage & PSA_KEY_USAGE_ENCRYPT ?
304             PSA_SUCCESS :
305             PSA_ERROR_INVALID_SIGNATURE);
306        status = psa_aead_decrypt(key, alg,
307                                  nonce, nonce_length,
308                                  NULL, 0,
309                                  ciphertext, ciphertext_length,
310                                  plaintext, sizeof(plaintext),
311                                  &plaintext_length);
312        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
313            /* The key has been destroyed. */
314            return 1;
315        }
316        TEST_ASSERT(status == verify_status);
317    }
318
319    return 1;
320
321exit:
322    psa_reset_key_attributes(&attributes);
323    return 0;
324}
325
326static int can_sign_or_verify_message(psa_key_usage_t usage,
327                                      psa_algorithm_t alg)
328{
329    /* Sign-the-unspecified-hash algorithms can only be used with
330     * {sign,verify}_hash, not with {sign,verify}_message. */
331    if (alg == PSA_ALG_ECDSA_ANY || alg == PSA_ALG_RSA_PKCS1V15_SIGN_RAW) {
332        return 0;
333    }
334    return usage & (PSA_KEY_USAGE_SIGN_MESSAGE |
335                    PSA_KEY_USAGE_VERIFY_MESSAGE);
336}
337
338static int exercise_signature_key(mbedtls_svc_key_id_t key,
339                                  psa_key_usage_t usage,
340                                  psa_algorithm_t alg,
341                                  int key_destroyable)
342{
343    /* If the policy allows signing with any hash, just pick one. */
344    psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);
345    if (PSA_ALG_IS_SIGN_HASH(alg) && hash_alg == PSA_ALG_ANY_HASH &&
346        usage & (PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH |
347                 PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE)) {
348#if defined(KNOWN_SUPPORTED_HASH_ALG)
349        hash_alg = KNOWN_SUPPORTED_HASH_ALG;
350        alg ^= PSA_ALG_ANY_HASH ^ hash_alg;
351#else
352        TEST_FAIL("No hash algorithm for hash-and-sign testing");
353#endif
354    }
355    psa_status_t status = PSA_SUCCESS;
356
357    if (usage & (PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH) &&
358        PSA_ALG_IS_SIGN_HASH(alg)) {
359        unsigned char payload[PSA_HASH_MAX_SIZE] = { 1 };
360        size_t payload_length = 16;
361        unsigned char signature[PSA_SIGNATURE_MAX_SIZE] = { 0 };
362        size_t signature_length = sizeof(signature);
363
364        /* Some algorithms require the payload to have the size of
365         * the hash encoded in the algorithm. Use this input size
366         * even for algorithms that allow other input sizes. */
367        if (hash_alg != 0) {
368            payload_length = PSA_HASH_LENGTH(hash_alg);
369        }
370
371        if (usage & PSA_KEY_USAGE_SIGN_HASH) {
372            status = psa_sign_hash(key, alg,
373                                   payload, payload_length,
374                                   signature, sizeof(signature),
375                                   &signature_length);
376            if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
377                /* The key has been destroyed. */
378                return 1;
379            }
380            PSA_ASSERT(status);
381        }
382
383        if (usage & PSA_KEY_USAGE_VERIFY_HASH) {
384            psa_status_t verify_status =
385                (usage & PSA_KEY_USAGE_SIGN_HASH ?
386                 PSA_SUCCESS :
387                 PSA_ERROR_INVALID_SIGNATURE);
388            status = psa_verify_hash(key, alg,
389                                     payload, payload_length,
390                                     signature, signature_length);
391            if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
392                /* The key has been destroyed. */
393                return 1;
394            }
395            TEST_ASSERT(status == verify_status);
396        }
397    }
398
399    if (can_sign_or_verify_message(usage, alg)) {
400        unsigned char message[256] = "Hello, world...";
401        unsigned char signature[PSA_SIGNATURE_MAX_SIZE] = { 0 };
402        size_t message_length = 16;
403        size_t signature_length = sizeof(signature);
404
405        if (usage & PSA_KEY_USAGE_SIGN_MESSAGE) {
406            status = psa_sign_message(key, alg,
407                                      message, message_length,
408                                      signature, sizeof(signature),
409                                      &signature_length);
410            if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
411                /* The key has been destroyed. */
412                return 1;
413            }
414            PSA_ASSERT(status);
415        }
416
417        if (usage & PSA_KEY_USAGE_VERIFY_MESSAGE) {
418            psa_status_t verify_status =
419                (usage & PSA_KEY_USAGE_SIGN_MESSAGE ?
420                 PSA_SUCCESS :
421                 PSA_ERROR_INVALID_SIGNATURE);
422            status = psa_verify_message(key, alg,
423                                        message, message_length,
424                                        signature, signature_length);
425            if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
426                /* The key has been destroyed. */
427                return 1;
428            }
429            TEST_ASSERT(status == verify_status);
430        }
431    }
432
433    return 1;
434
435exit:
436    return 0;
437}
438
439static int exercise_asymmetric_encryption_key(mbedtls_svc_key_id_t key,
440                                              psa_key_usage_t usage,
441                                              psa_algorithm_t alg,
442                                              int key_destroyable)
443{
444    unsigned char plaintext[PSA_ASYMMETRIC_DECRYPT_OUTPUT_MAX_SIZE] =
445        "Hello, world...";
446    unsigned char ciphertext[PSA_ASYMMETRIC_ENCRYPT_OUTPUT_MAX_SIZE] =
447        "(wabblewebblewibblewobblewubble)";
448    size_t ciphertext_length = sizeof(ciphertext);
449    size_t plaintext_length = 16;
450    psa_status_t status = PSA_SUCCESS;
451    if (usage & PSA_KEY_USAGE_ENCRYPT) {
452        status = psa_asymmetric_encrypt(key, alg,
453                                        plaintext, plaintext_length,
454                                        NULL, 0,
455                                        ciphertext, sizeof(ciphertext),
456                                        &ciphertext_length);
457        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
458            /* The key has been destroyed. */
459            return 1;
460        }
461        PSA_ASSERT(status);
462    }
463
464    if (usage & PSA_KEY_USAGE_DECRYPT) {
465        status = psa_asymmetric_decrypt(key, alg,
466                                        ciphertext, ciphertext_length,
467                                        NULL, 0,
468                                        plaintext, sizeof(plaintext),
469                                        &plaintext_length);
470        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
471            /* The key has been destroyed. */
472            return 1;
473        }
474        TEST_ASSERT(status == PSA_SUCCESS ||
475                    ((usage & PSA_KEY_USAGE_ENCRYPT) == 0 &&
476                     (status == PSA_ERROR_INVALID_ARGUMENT ||
477                      status == PSA_ERROR_INVALID_PADDING)));
478    }
479
480    return 1;
481
482exit:
483    return 0;
484}
485
486int mbedtls_test_psa_setup_key_derivation_wrap(
487    psa_key_derivation_operation_t *operation,
488    mbedtls_svc_key_id_t key,
489    psa_algorithm_t alg,
490    const unsigned char *input1, size_t input1_length,
491    const unsigned char *input2, size_t input2_length,
492    size_t capacity, int key_destroyable)
493{
494    PSA_ASSERT(psa_key_derivation_setup(operation, alg));
495    psa_status_t status = PSA_SUCCESS;
496    if (PSA_ALG_IS_HKDF(alg)) {
497        PSA_ASSERT(psa_key_derivation_input_bytes(operation,
498                                                  PSA_KEY_DERIVATION_INPUT_SALT,
499                                                  input1, input1_length));
500        status = psa_key_derivation_input_key(operation,
501                                              PSA_KEY_DERIVATION_INPUT_SECRET,
502                                              key);
503        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
504            /* The key has been destroyed. */
505            return 1;
506        }
507        PSA_ASSERT(status);
508        PSA_ASSERT(psa_key_derivation_input_bytes(operation,
509                                                  PSA_KEY_DERIVATION_INPUT_INFO,
510                                                  input2,
511                                                  input2_length));
512    } else if (PSA_ALG_IS_HKDF_EXTRACT(alg)) {
513        PSA_ASSERT(psa_key_derivation_input_bytes(operation,
514                                                  PSA_KEY_DERIVATION_INPUT_SALT,
515                                                  input1, input1_length));
516        status = psa_key_derivation_input_key(operation,
517                                              PSA_KEY_DERIVATION_INPUT_SECRET,
518                                              key);
519        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
520            /* The key has been destroyed. */
521            return 1;
522        }
523        PSA_ASSERT(status);
524    } else if (PSA_ALG_IS_HKDF_EXPAND(alg)) {
525        status = psa_key_derivation_input_key(operation,
526                                              PSA_KEY_DERIVATION_INPUT_SECRET,
527                                              key);
528        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
529            /* The key has been destroyed. */
530            return 1;
531        }
532        PSA_ASSERT(status);
533        PSA_ASSERT(psa_key_derivation_input_bytes(operation,
534                                                  PSA_KEY_DERIVATION_INPUT_INFO,
535                                                  input2,
536                                                  input2_length));
537    } else if (PSA_ALG_IS_TLS12_PRF(alg) ||
538               PSA_ALG_IS_TLS12_PSK_TO_MS(alg)) {
539        PSA_ASSERT(psa_key_derivation_input_bytes(operation,
540                                                  PSA_KEY_DERIVATION_INPUT_SEED,
541                                                  input1, input1_length));
542        status = psa_key_derivation_input_key(operation,
543                                              PSA_KEY_DERIVATION_INPUT_SECRET,
544                                              key);
545        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
546            /* The key has been destroyed. */
547            return 1;
548        }
549        PSA_ASSERT(status);
550        PSA_ASSERT(psa_key_derivation_input_bytes(operation,
551                                                  PSA_KEY_DERIVATION_INPUT_LABEL,
552                                                  input2, input2_length));
553    } else if (PSA_ALG_IS_PBKDF2(alg)) {
554        PSA_ASSERT(psa_key_derivation_input_integer(operation,
555                                                    PSA_KEY_DERIVATION_INPUT_COST,
556                                                    1U));
557        PSA_ASSERT(psa_key_derivation_input_bytes(operation,
558                                                  PSA_KEY_DERIVATION_INPUT_SALT,
559                                                  input2,
560                                                  input2_length));
561        status = psa_key_derivation_input_key(operation,
562                                              PSA_KEY_DERIVATION_INPUT_PASSWORD,
563                                              key);
564        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
565            /* The key has been destroyed. */
566            return 1;
567        }
568        PSA_ASSERT(status);
569    } else if (alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {
570        PSA_ASSERT(psa_key_derivation_input_bytes(operation,
571                                                  PSA_KEY_DERIVATION_INPUT_SECRET,
572                                                  input1, input1_length));
573    } else {
574        TEST_FAIL("Key derivation algorithm not supported");
575    }
576
577    if (capacity != SIZE_MAX) {
578        PSA_ASSERT(psa_key_derivation_set_capacity(operation, capacity));
579    }
580
581    return 1;
582
583exit:
584    return 0;
585}
586
587
588static int exercise_key_derivation_key(mbedtls_svc_key_id_t key,
589                                       psa_key_usage_t usage,
590                                       psa_algorithm_t alg,
591                                       int key_destroyable)
592{
593    psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
594    unsigned char input1[] = "Input 1";
595    size_t input1_length = sizeof(input1);
596    unsigned char input2[] = "Input 2";
597    size_t input2_length = sizeof(input2);
598    unsigned char output[1];
599    size_t capacity = sizeof(output);
600
601    if (usage & PSA_KEY_USAGE_DERIVE) {
602        if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, key, alg,
603                                                        input1, input1_length,
604                                                        input2, input2_length,
605                                                        capacity, key_destroyable)) {
606            goto exit;
607        }
608
609        psa_status_t status = psa_key_derivation_output_bytes(&operation,
610                                                              output,
611                                                              capacity);
612        if (key_destroyable && status == PSA_ERROR_BAD_STATE) {
613            /* The key has been destroyed. */
614            PSA_ASSERT(psa_key_derivation_abort(&operation));
615        } else {
616            PSA_ASSERT(status);
617            PSA_ASSERT(psa_key_derivation_abort(&operation));
618        }
619    }
620
621    return 1;
622
623exit:
624    return 0;
625}
626
627/* We need two keys to exercise key agreement. Exercise the
628 * private key against its own public key. */
629psa_status_t mbedtls_test_psa_key_agreement_with_self(
630    psa_key_derivation_operation_t *operation,
631    mbedtls_svc_key_id_t key, int key_destroyable)
632{
633    psa_key_type_t private_key_type;
634    psa_key_type_t public_key_type;
635    size_t key_bits;
636    uint8_t *public_key = NULL;
637    size_t public_key_length;
638    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
639
640    psa_status_t status = psa_get_key_attributes(key, &attributes);
641    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
642        /* The key has been destroyed. */
643        psa_reset_key_attributes(&attributes);
644        return PSA_SUCCESS;
645    }
646    PSA_ASSERT(status);
647
648    private_key_type = psa_get_key_type(&attributes);
649    key_bits = psa_get_key_bits(&attributes);
650    public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(private_key_type);
651    public_key_length = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(public_key_type, key_bits);
652    TEST_CALLOC(public_key, public_key_length);
653    status = psa_export_public_key(key, public_key, public_key_length,
654                                   &public_key_length);
655    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
656        /* The key has been destroyed. */
657        status = PSA_SUCCESS;
658        goto exit;
659    }
660    PSA_ASSERT(status);
661
662    status = psa_key_derivation_key_agreement(
663        operation, PSA_KEY_DERIVATION_INPUT_SECRET, key,
664        public_key, public_key_length);
665    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
666        /* The key has been destroyed. */
667        status = PSA_SUCCESS;
668        goto exit;
669    }
670exit:
671    /*
672     * Key attributes may have been returned by psa_get_key_attributes()
673     * thus reset them as required.
674     */
675    psa_reset_key_attributes(&attributes);
676
677    mbedtls_free(public_key);
678    return status;
679}
680
681/* We need two keys to exercise key agreement. Exercise the
682 * private key against its own public key. */
683psa_status_t mbedtls_test_psa_raw_key_agreement_with_self(
684    psa_algorithm_t alg,
685    mbedtls_svc_key_id_t key,
686    int key_destroyable)
687{
688    psa_key_type_t private_key_type;
689    psa_key_type_t public_key_type;
690    size_t key_bits;
691    uint8_t *public_key = NULL;
692    size_t public_key_length;
693    uint8_t output[1024];
694    size_t output_length;
695    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
696
697    psa_status_t status = psa_get_key_attributes(key, &attributes);
698    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
699        /* The key has been destroyed. */
700        psa_reset_key_attributes(&attributes);
701        return PSA_SUCCESS;
702    }
703    PSA_ASSERT(status);
704
705    private_key_type = psa_get_key_type(&attributes);
706    key_bits = psa_get_key_bits(&attributes);
707    public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(private_key_type);
708    public_key_length = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(public_key_type, key_bits);
709    TEST_CALLOC(public_key, public_key_length);
710    status = psa_export_public_key(key,
711                                   public_key, public_key_length,
712                                   &public_key_length);
713    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
714        /* The key has been destroyed. */
715        status = PSA_SUCCESS;
716        goto exit;
717    }
718    PSA_ASSERT(status);
719
720    status = psa_raw_key_agreement(alg, key,
721                                   public_key, public_key_length,
722                                   output, sizeof(output), &output_length);
723    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
724        /* The key has been destroyed. */
725        status = PSA_SUCCESS;
726        goto exit;
727    }
728    if (status == PSA_SUCCESS) {
729        TEST_ASSERT(output_length <=
730                    PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(private_key_type,
731                                                      key_bits));
732        TEST_ASSERT(output_length <=
733                    PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE);
734    }
735
736exit:
737    /*
738     * Key attributes may have been returned by psa_get_key_attributes()
739     * thus reset them as required.
740     */
741    psa_reset_key_attributes(&attributes);
742
743    mbedtls_free(public_key);
744    return status;
745}
746
747static int exercise_raw_key_agreement_key(mbedtls_svc_key_id_t key,
748                                          psa_key_usage_t usage,
749                                          psa_algorithm_t alg,
750                                          int key_destroyable)
751{
752    int ok = 0;
753
754    if (usage & PSA_KEY_USAGE_DERIVE) {
755        /* We need two keys to exercise key agreement. Exercise the
756         * private key against its own public key. */
757        PSA_ASSERT(mbedtls_test_psa_raw_key_agreement_with_self(alg, key,
758                                                                key_destroyable));
759    }
760    ok = 1;
761
762exit:
763    return ok;
764}
765
766static int exercise_key_agreement_key(mbedtls_svc_key_id_t key,
767                                      psa_key_usage_t usage,
768                                      psa_algorithm_t alg,
769                                      int key_destroyable)
770{
771    psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
772    unsigned char input[1] = { 0 };
773    unsigned char output[1];
774    int ok = 0;
775    psa_algorithm_t kdf_alg = PSA_ALG_KEY_AGREEMENT_GET_KDF(alg);
776    psa_status_t expected_key_agreement_status = PSA_SUCCESS;
777
778    if (usage & PSA_KEY_USAGE_DERIVE) {
779        /* We need two keys to exercise key agreement. Exercise the
780         * private key against its own public key. */
781        PSA_ASSERT(psa_key_derivation_setup(&operation, alg));
782        if (PSA_ALG_IS_TLS12_PRF(kdf_alg) ||
783            PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) {
784            PSA_ASSERT(psa_key_derivation_input_bytes(
785                           &operation, PSA_KEY_DERIVATION_INPUT_SEED,
786                           input, sizeof(input)));
787        }
788
789        if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) {
790            PSA_ASSERT(psa_key_derivation_input_bytes(
791                           &operation, PSA_KEY_DERIVATION_INPUT_SALT,
792                           input, sizeof(input)));
793        }
794
795        /* For HKDF_EXPAND input secret may fail as secret size may not match
796           to expected PRK size. In practice it means that key bits must match
797           hash length. Otherwise test should fail with INVALID_ARGUMENT. */
798        if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) {
799            psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
800            psa_status_t status = psa_get_key_attributes(key, &attributes);
801            if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
802                /* The key has been destroyed. */
803                ok = 1;
804            }
805            PSA_ASSERT(status);
806            size_t key_bits = psa_get_key_bits(&attributes);
807            psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(kdf_alg);
808
809            if (PSA_BITS_TO_BYTES(key_bits) != PSA_HASH_LENGTH(hash_alg)) {
810                expected_key_agreement_status = PSA_ERROR_INVALID_ARGUMENT;
811            }
812        }
813
814        TEST_EQUAL(mbedtls_test_psa_key_agreement_with_self(&operation, key,
815                                                            key_destroyable),
816                   expected_key_agreement_status);
817
818        if (expected_key_agreement_status != PSA_SUCCESS) {
819            return 1;
820        }
821
822        if (PSA_ALG_IS_TLS12_PRF(kdf_alg) ||
823            PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) {
824            PSA_ASSERT(psa_key_derivation_input_bytes(
825                           &operation, PSA_KEY_DERIVATION_INPUT_LABEL,
826                           input, sizeof(input)));
827        } else if (PSA_ALG_IS_HKDF(kdf_alg) || PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) {
828            PSA_ASSERT(psa_key_derivation_input_bytes(
829                           &operation, PSA_KEY_DERIVATION_INPUT_INFO,
830                           input, sizeof(input)));
831        }
832        PSA_ASSERT(psa_key_derivation_output_bytes(&operation,
833                                                   output,
834                                                   sizeof(output)));
835        PSA_ASSERT(psa_key_derivation_abort(&operation));
836    }
837    ok = 1;
838
839exit:
840    return ok;
841}
842
843int mbedtls_test_psa_exported_key_sanity_check(
844    psa_key_type_t type, size_t bits,
845    const uint8_t *exported, size_t exported_length)
846{
847    TEST_ASSERT(exported_length <= PSA_EXPORT_KEY_OUTPUT_SIZE(type, bits));
848
849    if (PSA_KEY_TYPE_IS_UNSTRUCTURED(type)) {
850        TEST_EQUAL(exported_length, PSA_BITS_TO_BYTES(bits));
851    } else
852
853#if defined(MBEDTLS_ASN1_PARSE_C)
854    if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
855        uint8_t *p = (uint8_t *) exported;
856        const uint8_t *end = exported + exported_length;
857        size_t len;
858        /*   RSAPrivateKey ::= SEQUENCE {
859         *       version             INTEGER,  -- must be 0
860         *       modulus             INTEGER,  -- n
861         *       publicExponent      INTEGER,  -- e
862         *       privateExponent     INTEGER,  -- d
863         *       prime1              INTEGER,  -- p
864         *       prime2              INTEGER,  -- q
865         *       exponent1           INTEGER,  -- d mod (p-1)
866         *       exponent2           INTEGER,  -- d mod (q-1)
867         *       coefficient         INTEGER,  -- (inverse of q) mod p
868         *   }
869         */
870        TEST_EQUAL(mbedtls_asn1_get_tag(&p, end, &len,
871                                        MBEDTLS_ASN1_SEQUENCE |
872                                        MBEDTLS_ASN1_CONSTRUCTED), 0);
873        TEST_EQUAL(len, end - p);
874        if (!mbedtls_test_asn1_skip_integer(&p, end, 0, 0, 0)) {
875            goto exit;
876        }
877        if (!mbedtls_test_asn1_skip_integer(&p, end, bits, bits, 1)) {
878            goto exit;
879        }
880        if (!mbedtls_test_asn1_skip_integer(&p, end, 2, bits, 1)) {
881            goto exit;
882        }
883        /* Require d to be at least half the size of n. */
884        if (!mbedtls_test_asn1_skip_integer(&p, end, bits / 2, bits, 1)) {
885            goto exit;
886        }
887        /* Require p and q to be at most half the size of n, rounded up. */
888        if (!mbedtls_test_asn1_skip_integer(&p, end, bits / 2, bits / 2 + 1, 1)) {
889            goto exit;
890        }
891        if (!mbedtls_test_asn1_skip_integer(&p, end, bits / 2, bits / 2 + 1, 1)) {
892            goto exit;
893        }
894        if (!mbedtls_test_asn1_skip_integer(&p, end, 1, bits / 2 + 1, 0)) {
895            goto exit;
896        }
897        if (!mbedtls_test_asn1_skip_integer(&p, end, 1, bits / 2 + 1, 0)) {
898            goto exit;
899        }
900        if (!mbedtls_test_asn1_skip_integer(&p, end, 1, bits / 2 + 1, 0)) {
901            goto exit;
902        }
903        TEST_EQUAL(p - end, 0);
904
905        TEST_ASSERT(exported_length <= PSA_EXPORT_KEY_PAIR_MAX_SIZE);
906    } else
907#endif /* MBEDTLS_ASN1_PARSE_C */
908
909    if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) {
910        /* Just the secret value */
911        TEST_EQUAL(exported_length, PSA_BITS_TO_BYTES(bits));
912
913        TEST_ASSERT(exported_length <= PSA_EXPORT_KEY_PAIR_MAX_SIZE);
914    } else
915
916#if defined(MBEDTLS_ASN1_PARSE_C)
917    if (type == PSA_KEY_TYPE_RSA_PUBLIC_KEY) {
918        uint8_t *p = (uint8_t *) exported;
919        const uint8_t *end = exported + exported_length;
920        size_t len;
921        /*   RSAPublicKey ::= SEQUENCE {
922         *      modulus            INTEGER,    -- n
923         *      publicExponent     INTEGER  }  -- e
924         */
925        TEST_EQUAL(mbedtls_asn1_get_tag(&p, end, &len,
926                                        MBEDTLS_ASN1_SEQUENCE |
927                                        MBEDTLS_ASN1_CONSTRUCTED),
928                   0);
929        TEST_EQUAL(len, end - p);
930        if (!mbedtls_test_asn1_skip_integer(&p, end, bits, bits, 1)) {
931            goto exit;
932        }
933        if (!mbedtls_test_asn1_skip_integer(&p, end, 2, bits, 1)) {
934            goto exit;
935        }
936        TEST_EQUAL(p - end, 0);
937
938
939        TEST_ASSERT(exported_length <=
940                    PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(type, bits));
941        TEST_ASSERT(exported_length <=
942                    PSA_EXPORT_PUBLIC_KEY_MAX_SIZE);
943    } else
944#endif /* MBEDTLS_ASN1_PARSE_C */
945
946    if (PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type)) {
947
948        TEST_ASSERT(exported_length <=
949                    PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(type, bits));
950        TEST_ASSERT(exported_length <=
951                    PSA_EXPORT_PUBLIC_KEY_MAX_SIZE);
952
953        if (PSA_KEY_TYPE_ECC_GET_FAMILY(type) == PSA_ECC_FAMILY_MONTGOMERY) {
954            /* The representation of an ECC Montgomery public key is
955             * the raw compressed point */
956            TEST_EQUAL(PSA_BITS_TO_BYTES(bits), exported_length);
957        } else if (PSA_KEY_TYPE_ECC_GET_FAMILY(type) == PSA_ECC_FAMILY_TWISTED_EDWARDS) {
958            /* The representation of an ECC Edwards public key is
959             * the raw compressed point */
960            TEST_EQUAL(PSA_BITS_TO_BYTES(bits + 1), exported_length);
961        } else {
962            /* The representation of an ECC Weierstrass public key is:
963             *      - The byte 0x04;
964             *      - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
965             *      - `y_P` as a `ceiling(m/8)`-byte string, big-endian;
966             *      - where m is the bit size associated with the curve.
967             */
968            TEST_EQUAL(1 + 2 * PSA_BITS_TO_BYTES(bits), exported_length);
969            TEST_EQUAL(exported[0], 4);
970        }
971    } else
972    if (PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(type) || PSA_KEY_TYPE_IS_DH_KEY_PAIR(type)) {
973        TEST_ASSERT(exported_length ==
974                    PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(type, bits));
975        TEST_ASSERT(exported_length <=
976                    PSA_EXPORT_PUBLIC_KEY_MAX_SIZE);
977    } else {
978        (void) exported;
979        TEST_FAIL("Sanity check not implemented for this key type");
980    }
981
982#if defined(MBEDTLS_DES_C)
983    if (type == PSA_KEY_TYPE_DES) {
984        /* Check the parity bits. */
985        unsigned i;
986        for (i = 0; i < bits / 8; i++) {
987            unsigned bit_count = 0;
988            unsigned m;
989            for (m = 1; m <= 0x100; m <<= 1) {
990                if (exported[i] & m) {
991                    ++bit_count;
992                }
993            }
994            TEST_ASSERT(bit_count % 2 != 0);
995        }
996    }
997#endif
998
999    return 1;
1000
1001exit:
1002    return 0;
1003}
1004
1005static int exercise_export_key(mbedtls_svc_key_id_t key,
1006                               psa_key_usage_t usage,
1007                               int key_destroyable)
1008{
1009    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
1010    uint8_t *exported = NULL;
1011    size_t exported_size = 0;
1012    size_t exported_length = 0;
1013    int ok = 0;
1014
1015    psa_status_t status = psa_get_key_attributes(key, &attributes);
1016    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
1017        /* The key has been destroyed. */
1018        psa_reset_key_attributes(&attributes);
1019        return 1;
1020    }
1021    PSA_ASSERT(status);
1022
1023    exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
1024        psa_get_key_type(&attributes),
1025        psa_get_key_bits(&attributes));
1026    TEST_CALLOC(exported, exported_size);
1027
1028    status = psa_export_key(key, exported, exported_size, &exported_length);
1029    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
1030        /* The key has been destroyed. */
1031        ok = 1;
1032        goto exit;
1033    } else if ((usage & PSA_KEY_USAGE_EXPORT) == 0 &&
1034               !PSA_KEY_TYPE_IS_PUBLIC_KEY(psa_get_key_type(&attributes))) {
1035        TEST_EQUAL(status, PSA_ERROR_NOT_PERMITTED);
1036        ok = 1;
1037        goto exit;
1038    }
1039    PSA_ASSERT(status);
1040    ok = mbedtls_test_psa_exported_key_sanity_check(
1041        psa_get_key_type(&attributes), psa_get_key_bits(&attributes),
1042        exported, exported_length);
1043
1044exit:
1045    /*
1046     * Key attributes may have been returned by psa_get_key_attributes()
1047     * thus reset them as required.
1048     */
1049    psa_reset_key_attributes(&attributes);
1050
1051    mbedtls_free(exported);
1052    return ok;
1053}
1054
1055static int exercise_export_public_key(mbedtls_svc_key_id_t key,
1056                                      int key_destroyable)
1057{
1058    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
1059    psa_key_type_t public_type;
1060    uint8_t *exported = NULL;
1061    size_t exported_size = 0;
1062    size_t exported_length = 0;
1063    int ok = 0;
1064
1065    psa_status_t status = psa_get_key_attributes(key, &attributes);
1066    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
1067        /* The key has been destroyed. */
1068        psa_reset_key_attributes(&attributes);
1069        return 1;
1070    }
1071    PSA_ASSERT(status);
1072    if (!PSA_KEY_TYPE_IS_ASYMMETRIC(psa_get_key_type(&attributes))) {
1073        exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
1074            psa_get_key_type(&attributes),
1075            psa_get_key_bits(&attributes));
1076        TEST_CALLOC(exported, exported_size);
1077
1078        status = psa_export_public_key(key, exported,
1079                                       exported_size, &exported_length);
1080        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
1081            /* The key has been destroyed. */
1082            ok = 1;
1083            goto exit;
1084        }
1085        TEST_EQUAL(status, PSA_ERROR_INVALID_ARGUMENT);
1086        ok = 1;
1087        goto exit;
1088    }
1089
1090    public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(
1091        psa_get_key_type(&attributes));
1092    exported_size = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(public_type,
1093                                                      psa_get_key_bits(&attributes));
1094    TEST_CALLOC(exported, exported_size);
1095
1096    status = psa_export_public_key(key, exported,
1097                                   exported_size, &exported_length);
1098    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
1099        /* The key has been destroyed. */
1100        ok = 1;
1101        goto exit;
1102    }
1103    PSA_ASSERT(status);
1104    ok = mbedtls_test_psa_exported_key_sanity_check(
1105        public_type, psa_get_key_bits(&attributes),
1106        exported, exported_length);
1107
1108exit:
1109    /*
1110     * Key attributes may have been returned by psa_get_key_attributes()
1111     * thus reset them as required.
1112     */
1113    psa_reset_key_attributes(&attributes);
1114
1115    mbedtls_free(exported);
1116    return ok;
1117}
1118
1119int mbedtls_test_psa_exercise_key(mbedtls_svc_key_id_t key,
1120                                  psa_key_usage_t usage,
1121                                  psa_algorithm_t alg,
1122                                  int key_destroyable)
1123{
1124    int ok = 0;
1125
1126    if (!check_key_attributes_sanity(key, key_destroyable)) {
1127        return 0;
1128    }
1129
1130    if (alg == 0) {
1131        ok = 1; /* If no algorithm, do nothing (used for raw data "keys"). */
1132    } else if (PSA_ALG_IS_MAC(alg)) {
1133        ok = exercise_mac_key(key, usage, alg, key_destroyable);
1134    } else if (PSA_ALG_IS_CIPHER(alg)) {
1135        ok = exercise_cipher_key(key, usage, alg, key_destroyable);
1136    } else if (PSA_ALG_IS_AEAD(alg)) {
1137        ok = exercise_aead_key(key, usage, alg, key_destroyable);
1138    } else if (PSA_ALG_IS_SIGN(alg)) {
1139        ok = exercise_signature_key(key, usage, alg, key_destroyable);
1140    } else if (PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg)) {
1141        ok = exercise_asymmetric_encryption_key(key, usage, alg,
1142                                                key_destroyable);
1143    } else if (PSA_ALG_IS_KEY_DERIVATION(alg)) {
1144        ok = exercise_key_derivation_key(key, usage, alg, key_destroyable);
1145    } else if (PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) {
1146        ok = exercise_raw_key_agreement_key(key, usage, alg, key_destroyable);
1147    } else if (PSA_ALG_IS_KEY_AGREEMENT(alg)) {
1148        ok = exercise_key_agreement_key(key, usage, alg, key_destroyable);
1149    } else {
1150        TEST_FAIL("No code to exercise this category of algorithm");
1151    }
1152
1153    ok = ok && exercise_export_key(key,
1154                                   usage,
1155                                   key_destroyable);
1156    ok = ok && exercise_export_public_key(key,
1157                                          key_destroyable);
1158
1159exit:
1160    return ok;
1161}
1162
1163psa_key_usage_t mbedtls_test_psa_usage_to_exercise(psa_key_type_t type,
1164                                                   psa_algorithm_t alg)
1165{
1166    if (PSA_ALG_IS_MAC(alg) || PSA_ALG_IS_SIGN(alg)) {
1167        if (PSA_ALG_IS_SIGN_HASH(alg)) {
1168            if (PSA_ALG_SIGN_GET_HASH(alg)) {
1169                return PSA_KEY_TYPE_IS_PUBLIC_KEY(type) ?
1170                       PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE :
1171                       PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH |
1172                       PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE;
1173            }
1174        } else if (PSA_ALG_IS_SIGN_MESSAGE(alg)) {
1175            return PSA_KEY_TYPE_IS_PUBLIC_KEY(type) ?
1176                   PSA_KEY_USAGE_VERIFY_MESSAGE :
1177                   PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE;
1178        }
1179
1180        return PSA_KEY_TYPE_IS_PUBLIC_KEY(type) ?
1181               PSA_KEY_USAGE_VERIFY_HASH :
1182               PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH;
1183    } else if (PSA_ALG_IS_CIPHER(alg) || PSA_ALG_IS_AEAD(alg) ||
1184               PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg)) {
1185        return PSA_KEY_TYPE_IS_PUBLIC_KEY(type) ?
1186               PSA_KEY_USAGE_ENCRYPT :
1187               PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT;
1188    } else if (PSA_ALG_IS_KEY_DERIVATION(alg) ||
1189               PSA_ALG_IS_KEY_AGREEMENT(alg)) {
1190        return PSA_KEY_USAGE_DERIVE;
1191    } else {
1192        return 0;
1193    }
1194
1195}
1196
1197int mbedtls_test_can_exercise_psa_algorithm(psa_algorithm_t alg)
1198{
1199    /* Reject algorithms that we know are not supported. Default to
1200     * attempting exercise, so that if an algorithm is missing from this
1201     * function, the result will be a test failure and not silently
1202     * omitting exercise. */
1203#if !defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT)
1204    if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) {
1205        return 0;
1206    }
1207#endif
1208#if !defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN)
1209    if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)) {
1210        return 0;
1211    }
1212#endif
1213#if !defined(PSA_WANT_ALG_RSA_PSS)
1214    if (PSA_ALG_IS_RSA_PSS_STANDARD_SALT(alg)) {
1215        return 0;
1216    }
1217#endif
1218#if !defined(PSA_WANT_ALG_RSA_PSS_ANY_SALT)
1219    if (PSA_ALG_IS_RSA_PSS_ANY_SALT(alg)) {
1220        return 0;
1221    }
1222#endif
1223#if !defined(PSA_WANT_ALG_ECDSA)
1224    if (PSA_ALG_IS_ECDSA(alg)) {
1225        return 0;
1226    }
1227#endif
1228#if !defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA)
1229    if (PSA_ALG_IS_DETERMINISTIC_ECDSA(alg)) {
1230        return 0;
1231    }
1232#endif
1233#if !defined(PSA_WANT_ALG_ECDH)
1234    if (PSA_ALG_IS_ECDH(alg)) {
1235        return 0;
1236    }
1237#endif
1238    (void) alg;
1239    return 1;
1240}
1241
1242#if defined(MBEDTLS_PK_C)
1243int mbedtls_test_key_consistency_psa_pk(mbedtls_svc_key_id_t psa_key,
1244                                        const mbedtls_pk_context *pk)
1245{
1246    psa_key_attributes_t psa_attributes = PSA_KEY_ATTRIBUTES_INIT;
1247    psa_key_attributes_t pk_attributes = PSA_KEY_ATTRIBUTES_INIT;
1248    int ok = 0;
1249
1250    PSA_ASSERT(psa_get_key_attributes(psa_key, &psa_attributes));
1251    psa_key_type_t psa_type = psa_get_key_type(&psa_attributes);
1252    mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk);
1253
1254    TEST_ASSERT(PSA_KEY_TYPE_IS_PUBLIC_KEY(psa_type) ||
1255                PSA_KEY_TYPE_IS_KEY_PAIR(psa_type));
1256    TEST_EQUAL(psa_get_key_bits(&psa_attributes), mbedtls_pk_get_bitlen(pk));
1257
1258    uint8_t pk_public_buffer[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
1259    const uint8_t *pk_public = NULL;
1260    size_t pk_public_length = 0;
1261
1262    switch (pk_type) {
1263#if defined(MBEDTLS_RSA_C)
1264        case MBEDTLS_PK_RSA:
1265            TEST_ASSERT(PSA_KEY_TYPE_IS_RSA(psa_type));
1266            const mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk);
1267            uint8_t *const end = pk_public_buffer + sizeof(pk_public_buffer);
1268            uint8_t *cursor = end;
1269            TEST_LE_U(1, mbedtls_rsa_write_pubkey(rsa,
1270                                                  pk_public_buffer, &cursor));
1271            pk_public = cursor;
1272            pk_public_length = end - pk_public;
1273            break;
1274#endif
1275
1276#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
1277        case MBEDTLS_PK_ECKEY:
1278        case MBEDTLS_PK_ECKEY_DH:
1279        case MBEDTLS_PK_ECDSA:
1280            TEST_ASSERT(PSA_KEY_TYPE_IS_ECC(psa_type));
1281            TEST_EQUAL(PSA_KEY_TYPE_ECC_GET_FAMILY(psa_type), pk->ec_family);
1282            pk_public = pk->pub_raw;
1283            pk_public_length = pk->pub_raw_len;
1284            break;
1285#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
1286
1287#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_PK_USE_PSA_EC_DATA)
1288        case MBEDTLS_PK_ECKEY:
1289        case MBEDTLS_PK_ECKEY_DH:
1290        case MBEDTLS_PK_ECDSA:
1291            TEST_ASSERT(PSA_KEY_TYPE_IS_ECC(psa_get_key_type(&psa_attributes)));
1292            const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk);
1293            TEST_EQUAL(mbedtls_ecp_write_public_key(
1294                           ec, MBEDTLS_ECP_PF_UNCOMPRESSED, &pk_public_length,
1295                           pk_public_buffer, sizeof(pk_public_buffer)), 0);
1296            pk_public = pk_public_buffer;
1297            break;
1298#endif /* MBEDTLS_PK_HAVE_ECC_KEYS && !MBEDTLS_PK_USE_PSA_EC_DATA */
1299
1300#if defined(MBEDTLS_USE_PSA_CRYPTO)
1301        case MBEDTLS_PK_OPAQUE:
1302            PSA_ASSERT(psa_get_key_attributes(pk->priv_id, &pk_attributes));
1303            psa_key_type_t pk_psa_type = psa_get_key_type(&pk_attributes);
1304            TEST_EQUAL(PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(psa_type),
1305                       PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(pk_psa_type));
1306            PSA_ASSERT(psa_export_public_key(psa_key,
1307                                             pk_public_buffer,
1308                                             sizeof(pk_public_buffer),
1309                                             &pk_public_length));
1310            pk_public = pk_public_buffer;
1311            break;
1312#endif /* MBEDTLS_USE_PSA_CRYPTO */
1313
1314        default:
1315            TEST_FAIL("pk type not supported");
1316    }
1317
1318    uint8_t psa_public[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
1319    size_t psa_public_length = 0;
1320    PSA_ASSERT(psa_export_public_key(psa_key,
1321                                     psa_public, sizeof(psa_public),
1322                                     &psa_public_length));
1323    TEST_MEMORY_COMPARE(pk_public, pk_public_length,
1324                        psa_public, psa_public_length);
1325
1326    ok = 1;
1327
1328exit:
1329    psa_reset_key_attributes(&psa_attributes);
1330    psa_reset_key_attributes(&pk_attributes);
1331    return ok;
1332}
1333#endif /* MBEDTLS_PK_C */
1334
1335#endif /* MBEDTLS_PSA_CRYPTO_C */
1336