psa_crypto_helpers.c (8578B)
1 /** \file psa_crypto_helpers.c 2 * 3 * \brief Helper functions to test PSA crypto functionality. 4 */ 5 6 /* 7 * Copyright The Mbed TLS Contributors 8 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 9 */ 10 11 #include <test/helpers.h> 12 #include <test/macros.h> 13 #include <psa_crypto_slot_management.h> 14 #include <test/psa_crypto_helpers.h> 15 16 #if defined(MBEDTLS_CTR_DRBG_C) 17 #include <mbedtls/ctr_drbg.h> 18 #endif 19 20 #if defined(MBEDTLS_PSA_CRYPTO_C) 21 22 #include <psa/crypto.h> 23 24 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) 25 26 #include <psa_crypto_storage.h> 27 28 static mbedtls_svc_key_id_t key_ids_used_in_test[9]; 29 static size_t num_key_ids_used; 30 31 int mbedtls_test_uses_key_id(mbedtls_svc_key_id_t key_id) 32 { 33 size_t i; 34 if (MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key_id) > 35 PSA_MAX_PERSISTENT_KEY_IDENTIFIER) { 36 /* Don't touch key id values that designate non-key files. */ 37 return 1; 38 } 39 for (i = 0; i < num_key_ids_used; i++) { 40 if (mbedtls_svc_key_id_equal(key_id, key_ids_used_in_test[i])) { 41 return 1; 42 } 43 } 44 if (num_key_ids_used == ARRAY_LENGTH(key_ids_used_in_test)) { 45 return 0; 46 } 47 key_ids_used_in_test[num_key_ids_used] = key_id; 48 ++num_key_ids_used; 49 return 1; 50 } 51 52 void mbedtls_test_psa_purge_key_storage(void) 53 { 54 size_t i; 55 for (i = 0; i < num_key_ids_used; i++) { 56 psa_destroy_persistent_key(key_ids_used_in_test[i]); 57 } 58 num_key_ids_used = 0; 59 } 60 61 void mbedtls_test_psa_purge_key_cache(void) 62 { 63 size_t i; 64 for (i = 0; i < num_key_ids_used; i++) { 65 psa_purge_key(key_ids_used_in_test[i]); 66 } 67 } 68 69 #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ 70 71 const char *mbedtls_test_helper_is_psa_leaking(void) 72 { 73 mbedtls_psa_stats_t stats; 74 75 mbedtls_psa_get_stats(&stats); 76 77 /* Some volatile slots may be used for internal purposes. Generally 78 * we'll have exactly MBEDTLS_TEST_PSA_INTERNAL_KEYS at this point, 79 * but in some cases we might have less, e.g. if a code path calls 80 * PSA_DONE more than once, or if there has only been a partial or 81 * failed initialization. */ 82 if (stats.volatile_slots > MBEDTLS_TEST_PSA_INTERNAL_KEYS) { 83 return "A volatile slot has not been closed properly."; 84 } 85 if (stats.persistent_slots != 0) { 86 return "A persistent slot has not been closed properly."; 87 } 88 if (stats.external_slots != 0) { 89 return "An external slot has not been closed properly."; 90 } 91 if (stats.half_filled_slots != 0) { 92 return "A half-filled slot has not been cleared properly."; 93 } 94 if (stats.locked_slots != 0) { 95 return "Some slots are still marked as locked."; 96 } 97 98 return NULL; 99 } 100 101 102 103 psa_hash_operation_t psa_hash_operation_init_short(void) 104 { 105 psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; 106 memset(&operation.ctx, '!', sizeof(operation.ctx)); 107 return operation; 108 } 109 110 psa_mac_operation_t psa_mac_operation_init_short(void) 111 { 112 psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; 113 memset(&operation.ctx, '!', sizeof(operation.ctx)); 114 return operation; 115 } 116 117 psa_cipher_operation_t psa_cipher_operation_init_short(void) 118 { 119 psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; 120 memset(&operation.ctx, '!', sizeof(operation.ctx)); 121 return operation; 122 } 123 124 psa_aead_operation_t psa_aead_operation_init_short(void) 125 { 126 psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT; 127 memset(&operation.ctx, '!', sizeof(operation.ctx)); 128 return operation; 129 } 130 131 psa_key_derivation_operation_t psa_key_derivation_operation_init_short(void) 132 { 133 psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; 134 memset(&operation.ctx, '!', sizeof(operation.ctx)); 135 return operation; 136 } 137 138 psa_pake_operation_t psa_pake_operation_init_short(void) 139 { 140 psa_pake_operation_t operation = PSA_PAKE_OPERATION_INIT; 141 memset(&operation.computation_stage, '!', sizeof(operation.computation_stage)); 142 memset(&operation.data, '!', sizeof(operation.data)); 143 return operation; 144 } 145 146 psa_sign_hash_interruptible_operation_t psa_sign_hash_interruptible_operation_init_short(void) 147 { 148 psa_sign_hash_interruptible_operation_t operation = 149 PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT; 150 memset(&operation.ctx, '!', sizeof(operation.ctx)); 151 return operation; 152 } 153 154 psa_verify_hash_interruptible_operation_t psa_verify_hash_interruptible_operation_init_short(void) 155 { 156 psa_verify_hash_interruptible_operation_t operation = 157 PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT; 158 memset(&operation.ctx, '!', sizeof(operation.ctx)); 159 return operation; 160 } 161 162 #if defined(PSA_KEY_AGREEMENT_IOP_INIT) 163 psa_key_agreement_iop_t psa_key_agreement_iop_init_short(void) 164 { 165 psa_key_agreement_iop_t operation = PSA_KEY_AGREEMENT_IOP_INIT; 166 /* No driver support, and thus no union, yet, at the time of writing */ 167 return operation; 168 } 169 #endif 170 171 #if defined(PSA_GENERATE_KEY_IOP_INIT) 172 psa_generate_key_iop_t psa_generate_key_iop_init_short(void) 173 { 174 psa_generate_key_iop_t operation = PSA_GENERATE_KEY_IOP_INIT; 175 /* No driver support, and thus no union, yet, at the time of writing */ 176 return operation; 177 } 178 #endif 179 180 #if defined(PSA_EXPORT_PUBLIC_KEY_IOP_INIT) 181 psa_export_public_key_iop_t psa_export_public_key_iop_init_short(void) 182 { 183 psa_export_public_key_iop_t operation = PSA_EXPORT_PUBLIC_KEY_IOP_INIT; 184 /* No driver support, and thus no union, yet, at the time of writing */ 185 return operation; 186 } 187 #endif 188 189 190 191 #if defined(RECORD_PSA_STATUS_COVERAGE_LOG) 192 /** Name of the file where return statuses are logged by #RECORD_STATUS. */ 193 #define STATUS_LOG_FILE_NAME "statuses.log" 194 195 psa_status_t mbedtls_test_record_status(psa_status_t status, 196 const char *func, 197 const char *file, int line, 198 const char *expr) 199 { 200 /* We open the log file on first use. 201 * We never close the log file, so the record_status feature is not 202 * compatible with resource leak detectors such as Asan. 203 */ 204 static FILE *log; 205 if (log == NULL) { 206 log = fopen(STATUS_LOG_FILE_NAME, "a"); 207 } 208 fprintf(log, "%d:%s:%s:%d:%s\n", (int) status, func, file, line, expr); 209 return status; 210 } 211 #endif /* defined(RECORD_PSA_STATUS_COVERAGE_LOG) */ 212 213 psa_key_usage_t mbedtls_test_update_key_usage_flags(psa_key_usage_t usage_flags) 214 { 215 psa_key_usage_t updated_usage = usage_flags; 216 217 if (usage_flags & PSA_KEY_USAGE_SIGN_HASH) { 218 updated_usage |= PSA_KEY_USAGE_SIGN_MESSAGE; 219 } 220 221 if (usage_flags & PSA_KEY_USAGE_VERIFY_HASH) { 222 updated_usage |= PSA_KEY_USAGE_VERIFY_MESSAGE; 223 } 224 225 return updated_usage; 226 } 227 228 int mbedtls_test_fail_if_psa_leaking(int line_no, const char *filename) 229 { 230 const char *msg = mbedtls_test_helper_is_psa_leaking(); 231 if (msg == NULL) { 232 return 0; 233 } else { 234 mbedtls_test_fail(msg, line_no, filename); 235 return 1; 236 } 237 } 238 239 uint64_t mbedtls_test_parse_binary_string(data_t *bin_string) 240 { 241 uint64_t result = 0; 242 TEST_LE_U(bin_string->len, 8); 243 for (size_t i = 0; i < bin_string->len; i++) { 244 result = result << 8 | bin_string->x[i]; 245 } 246 exit: 247 return result; /* returns 0 if len > 8 */ 248 } 249 250 #if defined(MBEDTLS_PSA_INJECT_ENTROPY) 251 252 #include <mbedtls/entropy.h> 253 #include <psa_crypto_its.h> 254 255 int mbedtls_test_inject_entropy_seed_read(unsigned char *buf, size_t len) 256 { 257 size_t actual_len = 0; 258 psa_status_t status = psa_its_get(PSA_CRYPTO_ITS_RANDOM_SEED_UID, 259 0, len, buf, &actual_len); 260 if (status != 0) { 261 return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; 262 } 263 if (actual_len != len) { 264 return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; 265 } 266 return 0; 267 } 268 269 int mbedtls_test_inject_entropy_seed_write(unsigned char *buf, size_t len) 270 { 271 psa_status_t status = psa_its_set(PSA_CRYPTO_ITS_RANDOM_SEED_UID, 272 len, buf, 0); 273 if (status != 0) { 274 return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; 275 } 276 return 0; 277 } 278 279 int mbedtls_test_inject_entropy_restore(void) 280 { 281 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; 282 for (size_t i = 0; i < sizeof(buf); i++) { 283 buf[i] = (unsigned char) i; 284 } 285 psa_status_t status = mbedtls_psa_inject_entropy(buf, sizeof(buf)); 286 /* It's ok if the file was just created, or if it already exists. */ 287 if (status != PSA_SUCCESS && status != PSA_ERROR_NOT_PERMITTED) { 288 return status; 289 } 290 return PSA_SUCCESS; 291 } 292 293 #endif /* MBEDTLS_PSA_INJECT_ENTROPY */ 294 295 #endif /* MBEDTLS_PSA_CRYPTO_C */