1*62c56f98SSadaf Ebrahimi /** \file psa_crypto_helpers.c
2*62c56f98SSadaf Ebrahimi *
3*62c56f98SSadaf Ebrahimi * \brief Helper functions to test PSA crypto functionality.
4*62c56f98SSadaf Ebrahimi */
5*62c56f98SSadaf Ebrahimi
6*62c56f98SSadaf Ebrahimi /*
7*62c56f98SSadaf Ebrahimi * Copyright The Mbed TLS Contributors
8*62c56f98SSadaf Ebrahimi * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
9*62c56f98SSadaf Ebrahimi */
10*62c56f98SSadaf Ebrahimi
11*62c56f98SSadaf Ebrahimi #include <test/helpers.h>
12*62c56f98SSadaf Ebrahimi #include <test/macros.h>
13*62c56f98SSadaf Ebrahimi #include <psa_crypto_slot_management.h>
14*62c56f98SSadaf Ebrahimi #include <test/psa_crypto_helpers.h>
15*62c56f98SSadaf Ebrahimi
16*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PSA_CRYPTO_C)
17*62c56f98SSadaf Ebrahimi
18*62c56f98SSadaf Ebrahimi #include <psa/crypto.h>
19*62c56f98SSadaf Ebrahimi
20*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
21*62c56f98SSadaf Ebrahimi
22*62c56f98SSadaf Ebrahimi #include <psa_crypto_storage.h>
23*62c56f98SSadaf Ebrahimi
24*62c56f98SSadaf Ebrahimi static mbedtls_svc_key_id_t key_ids_used_in_test[9];
25*62c56f98SSadaf Ebrahimi static size_t num_key_ids_used;
26*62c56f98SSadaf Ebrahimi
mbedtls_test_uses_key_id(mbedtls_svc_key_id_t key_id)27*62c56f98SSadaf Ebrahimi int mbedtls_test_uses_key_id(mbedtls_svc_key_id_t key_id)
28*62c56f98SSadaf Ebrahimi {
29*62c56f98SSadaf Ebrahimi size_t i;
30*62c56f98SSadaf Ebrahimi if (MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key_id) >
31*62c56f98SSadaf Ebrahimi PSA_MAX_PERSISTENT_KEY_IDENTIFIER) {
32*62c56f98SSadaf Ebrahimi /* Don't touch key id values that designate non-key files. */
33*62c56f98SSadaf Ebrahimi return 1;
34*62c56f98SSadaf Ebrahimi }
35*62c56f98SSadaf Ebrahimi for (i = 0; i < num_key_ids_used; i++) {
36*62c56f98SSadaf Ebrahimi if (mbedtls_svc_key_id_equal(key_id, key_ids_used_in_test[i])) {
37*62c56f98SSadaf Ebrahimi return 1;
38*62c56f98SSadaf Ebrahimi }
39*62c56f98SSadaf Ebrahimi }
40*62c56f98SSadaf Ebrahimi if (num_key_ids_used == ARRAY_LENGTH(key_ids_used_in_test)) {
41*62c56f98SSadaf Ebrahimi return 0;
42*62c56f98SSadaf Ebrahimi }
43*62c56f98SSadaf Ebrahimi key_ids_used_in_test[num_key_ids_used] = key_id;
44*62c56f98SSadaf Ebrahimi ++num_key_ids_used;
45*62c56f98SSadaf Ebrahimi return 1;
46*62c56f98SSadaf Ebrahimi }
47*62c56f98SSadaf Ebrahimi
mbedtls_test_psa_purge_key_storage(void)48*62c56f98SSadaf Ebrahimi void mbedtls_test_psa_purge_key_storage(void)
49*62c56f98SSadaf Ebrahimi {
50*62c56f98SSadaf Ebrahimi size_t i;
51*62c56f98SSadaf Ebrahimi for (i = 0; i < num_key_ids_used; i++) {
52*62c56f98SSadaf Ebrahimi psa_destroy_persistent_key(key_ids_used_in_test[i]);
53*62c56f98SSadaf Ebrahimi }
54*62c56f98SSadaf Ebrahimi num_key_ids_used = 0;
55*62c56f98SSadaf Ebrahimi }
56*62c56f98SSadaf Ebrahimi
mbedtls_test_psa_purge_key_cache(void)57*62c56f98SSadaf Ebrahimi void mbedtls_test_psa_purge_key_cache(void)
58*62c56f98SSadaf Ebrahimi {
59*62c56f98SSadaf Ebrahimi size_t i;
60*62c56f98SSadaf Ebrahimi for (i = 0; i < num_key_ids_used; i++) {
61*62c56f98SSadaf Ebrahimi psa_purge_key(key_ids_used_in_test[i]);
62*62c56f98SSadaf Ebrahimi }
63*62c56f98SSadaf Ebrahimi }
64*62c56f98SSadaf Ebrahimi
65*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
66*62c56f98SSadaf Ebrahimi
mbedtls_test_helper_is_psa_leaking(void)67*62c56f98SSadaf Ebrahimi const char *mbedtls_test_helper_is_psa_leaking(void)
68*62c56f98SSadaf Ebrahimi {
69*62c56f98SSadaf Ebrahimi mbedtls_psa_stats_t stats;
70*62c56f98SSadaf Ebrahimi
71*62c56f98SSadaf Ebrahimi mbedtls_psa_get_stats(&stats);
72*62c56f98SSadaf Ebrahimi
73*62c56f98SSadaf Ebrahimi if (stats.volatile_slots != 0) {
74*62c56f98SSadaf Ebrahimi return "A volatile slot has not been closed properly.";
75*62c56f98SSadaf Ebrahimi }
76*62c56f98SSadaf Ebrahimi if (stats.persistent_slots != 0) {
77*62c56f98SSadaf Ebrahimi return "A persistent slot has not been closed properly.";
78*62c56f98SSadaf Ebrahimi }
79*62c56f98SSadaf Ebrahimi if (stats.external_slots != 0) {
80*62c56f98SSadaf Ebrahimi return "An external slot has not been closed properly.";
81*62c56f98SSadaf Ebrahimi }
82*62c56f98SSadaf Ebrahimi if (stats.half_filled_slots != 0) {
83*62c56f98SSadaf Ebrahimi return "A half-filled slot has not been cleared properly.";
84*62c56f98SSadaf Ebrahimi }
85*62c56f98SSadaf Ebrahimi if (stats.locked_slots != 0) {
86*62c56f98SSadaf Ebrahimi return "Some slots are still marked as locked.";
87*62c56f98SSadaf Ebrahimi }
88*62c56f98SSadaf Ebrahimi
89*62c56f98SSadaf Ebrahimi return NULL;
90*62c56f98SSadaf Ebrahimi }
91*62c56f98SSadaf Ebrahimi
92*62c56f98SSadaf Ebrahimi #if defined(RECORD_PSA_STATUS_COVERAGE_LOG)
93*62c56f98SSadaf Ebrahimi /** Name of the file where return statuses are logged by #RECORD_STATUS. */
94*62c56f98SSadaf Ebrahimi #define STATUS_LOG_FILE_NAME "statuses.log"
95*62c56f98SSadaf Ebrahimi
mbedtls_test_record_status(psa_status_t status,const char * func,const char * file,int line,const char * expr)96*62c56f98SSadaf Ebrahimi psa_status_t mbedtls_test_record_status(psa_status_t status,
97*62c56f98SSadaf Ebrahimi const char *func,
98*62c56f98SSadaf Ebrahimi const char *file, int line,
99*62c56f98SSadaf Ebrahimi const char *expr)
100*62c56f98SSadaf Ebrahimi {
101*62c56f98SSadaf Ebrahimi /* We open the log file on first use.
102*62c56f98SSadaf Ebrahimi * We never close the log file, so the record_status feature is not
103*62c56f98SSadaf Ebrahimi * compatible with resource leak detectors such as Asan.
104*62c56f98SSadaf Ebrahimi */
105*62c56f98SSadaf Ebrahimi static FILE *log;
106*62c56f98SSadaf Ebrahimi if (log == NULL) {
107*62c56f98SSadaf Ebrahimi log = fopen(STATUS_LOG_FILE_NAME, "a");
108*62c56f98SSadaf Ebrahimi }
109*62c56f98SSadaf Ebrahimi fprintf(log, "%d:%s:%s:%d:%s\n", (int) status, func, file, line, expr);
110*62c56f98SSadaf Ebrahimi return status;
111*62c56f98SSadaf Ebrahimi }
112*62c56f98SSadaf Ebrahimi #endif /* defined(RECORD_PSA_STATUS_COVERAGE_LOG) */
113*62c56f98SSadaf Ebrahimi
mbedtls_test_update_key_usage_flags(psa_key_usage_t usage_flags)114*62c56f98SSadaf Ebrahimi psa_key_usage_t mbedtls_test_update_key_usage_flags(psa_key_usage_t usage_flags)
115*62c56f98SSadaf Ebrahimi {
116*62c56f98SSadaf Ebrahimi psa_key_usage_t updated_usage = usage_flags;
117*62c56f98SSadaf Ebrahimi
118*62c56f98SSadaf Ebrahimi if (usage_flags & PSA_KEY_USAGE_SIGN_HASH) {
119*62c56f98SSadaf Ebrahimi updated_usage |= PSA_KEY_USAGE_SIGN_MESSAGE;
120*62c56f98SSadaf Ebrahimi }
121*62c56f98SSadaf Ebrahimi
122*62c56f98SSadaf Ebrahimi if (usage_flags & PSA_KEY_USAGE_VERIFY_HASH) {
123*62c56f98SSadaf Ebrahimi updated_usage |= PSA_KEY_USAGE_VERIFY_MESSAGE;
124*62c56f98SSadaf Ebrahimi }
125*62c56f98SSadaf Ebrahimi
126*62c56f98SSadaf Ebrahimi return updated_usage;
127*62c56f98SSadaf Ebrahimi }
128*62c56f98SSadaf Ebrahimi
mbedtls_test_fail_if_psa_leaking(int line_no,const char * filename)129*62c56f98SSadaf Ebrahimi int mbedtls_test_fail_if_psa_leaking(int line_no, const char *filename)
130*62c56f98SSadaf Ebrahimi {
131*62c56f98SSadaf Ebrahimi const char *msg = mbedtls_test_helper_is_psa_leaking();
132*62c56f98SSadaf Ebrahimi if (msg == NULL) {
133*62c56f98SSadaf Ebrahimi return 0;
134*62c56f98SSadaf Ebrahimi } else {
135*62c56f98SSadaf Ebrahimi mbedtls_test_fail(msg, line_no, filename);
136*62c56f98SSadaf Ebrahimi return 1;
137*62c56f98SSadaf Ebrahimi }
138*62c56f98SSadaf Ebrahimi }
139*62c56f98SSadaf Ebrahimi
mbedtls_test_parse_binary_string(data_t * bin_string)140*62c56f98SSadaf Ebrahimi uint64_t mbedtls_test_parse_binary_string(data_t *bin_string)
141*62c56f98SSadaf Ebrahimi {
142*62c56f98SSadaf Ebrahimi uint64_t result = 0;
143*62c56f98SSadaf Ebrahimi TEST_LE_U(bin_string->len, 8);
144*62c56f98SSadaf Ebrahimi for (size_t i = 0; i < bin_string->len; i++) {
145*62c56f98SSadaf Ebrahimi result = result << 8 | bin_string->x[i];
146*62c56f98SSadaf Ebrahimi }
147*62c56f98SSadaf Ebrahimi exit:
148*62c56f98SSadaf Ebrahimi return result; /* returns 0 if len > 8 */
149*62c56f98SSadaf Ebrahimi }
150*62c56f98SSadaf Ebrahimi
151*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PSA_INJECT_ENTROPY)
152*62c56f98SSadaf Ebrahimi
153*62c56f98SSadaf Ebrahimi #include <mbedtls/entropy.h>
154*62c56f98SSadaf Ebrahimi #include <psa_crypto_its.h>
155*62c56f98SSadaf Ebrahimi
mbedtls_test_inject_entropy_seed_read(unsigned char * buf,size_t len)156*62c56f98SSadaf Ebrahimi int mbedtls_test_inject_entropy_seed_read(unsigned char *buf, size_t len)
157*62c56f98SSadaf Ebrahimi {
158*62c56f98SSadaf Ebrahimi size_t actual_len = 0;
159*62c56f98SSadaf Ebrahimi psa_status_t status = psa_its_get(PSA_CRYPTO_ITS_RANDOM_SEED_UID,
160*62c56f98SSadaf Ebrahimi 0, len, buf, &actual_len);
161*62c56f98SSadaf Ebrahimi if (status != 0) {
162*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
163*62c56f98SSadaf Ebrahimi }
164*62c56f98SSadaf Ebrahimi if (actual_len != len) {
165*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
166*62c56f98SSadaf Ebrahimi }
167*62c56f98SSadaf Ebrahimi return 0;
168*62c56f98SSadaf Ebrahimi }
169*62c56f98SSadaf Ebrahimi
mbedtls_test_inject_entropy_seed_write(unsigned char * buf,size_t len)170*62c56f98SSadaf Ebrahimi int mbedtls_test_inject_entropy_seed_write(unsigned char *buf, size_t len)
171*62c56f98SSadaf Ebrahimi {
172*62c56f98SSadaf Ebrahimi psa_status_t status = psa_its_set(PSA_CRYPTO_ITS_RANDOM_SEED_UID,
173*62c56f98SSadaf Ebrahimi len, buf, 0);
174*62c56f98SSadaf Ebrahimi if (status != 0) {
175*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
176*62c56f98SSadaf Ebrahimi }
177*62c56f98SSadaf Ebrahimi return 0;
178*62c56f98SSadaf Ebrahimi }
179*62c56f98SSadaf Ebrahimi
mbedtls_test_inject_entropy_restore(void)180*62c56f98SSadaf Ebrahimi int mbedtls_test_inject_entropy_restore(void)
181*62c56f98SSadaf Ebrahimi {
182*62c56f98SSadaf Ebrahimi unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
183*62c56f98SSadaf Ebrahimi for (size_t i = 0; i < sizeof(buf); i++) {
184*62c56f98SSadaf Ebrahimi buf[i] = (unsigned char) i;
185*62c56f98SSadaf Ebrahimi }
186*62c56f98SSadaf Ebrahimi psa_status_t status = mbedtls_psa_inject_entropy(buf, sizeof(buf));
187*62c56f98SSadaf Ebrahimi /* It's ok if the file was just created, or if it already exists. */
188*62c56f98SSadaf Ebrahimi if (status != PSA_SUCCESS && status != PSA_ERROR_NOT_PERMITTED) {
189*62c56f98SSadaf Ebrahimi return status;
190*62c56f98SSadaf Ebrahimi }
191*62c56f98SSadaf Ebrahimi return PSA_SUCCESS;
192*62c56f98SSadaf Ebrahimi }
193*62c56f98SSadaf Ebrahimi
194*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PSA_INJECT_ENTROPY */
195*62c56f98SSadaf Ebrahimi
196*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PSA_CRYPTO_C */
197