quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

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 */