/* BEGIN_HEADER */ #include "psa/crypto_se_driver.h" #include "psa_crypto_se.h" #include "psa_crypto_slot_management.h" #include "psa_crypto_storage.h" /* Invasive peeking: check the persistent data */ #if defined(MBEDTLS_PSA_ITS_FILE_C) #include "psa_crypto_its.h" #else /* Native ITS implementation */ #include "psa/error.h" #include "psa/internal_trusted_storage.h" #endif /****************************************************************/ /* Test driver helpers */ /****************************************************************/ /** The minimum valid location value for a secure element driver. */ #define MIN_DRIVER_LOCATION 1 /** The location and lifetime used for tests that use a single driver. */ #define TEST_DRIVER_LOCATION 1 #define TEST_SE_PERSISTENT_LIFETIME \ (PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( \ PSA_KEY_PERSISTENCE_DEFAULT, TEST_DRIVER_LOCATION)) #define TEST_SE_VOLATILE_LIFETIME \ (PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( \ PSA_KEY_PERSISTENCE_VOLATILE, TEST_DRIVER_LOCATION)) /** The driver detected a condition that shouldn't happen. * This is probably a bug in the library. */ #define PSA_ERROR_DETECTED_BY_DRIVER ((psa_status_t) (-500)) /** Like #TEST_ASSERT for use in a driver method, with no cleanup. * * If an error happens, this macro returns from the calling function. * * Use this macro to assert on guarantees provided by the core. */ #define DRIVER_ASSERT_RETURN(TEST) \ do { \ if (!(TEST)) \ { \ mbedtls_test_fail( #TEST, __LINE__, __FILE__); \ return PSA_ERROR_DETECTED_BY_DRIVER; \ } \ } while (0) /** Like #TEST_ASSERT for use in a driver method, with cleanup. * * In case of error, this macro sets `status` and jumps to the * label `exit`. * * Use this macro to assert on guarantees provided by the core. */ #define DRIVER_ASSERT(TEST) \ do { \ if (!(TEST)) \ { \ mbedtls_test_fail( #TEST, __LINE__, __FILE__); \ status = PSA_ERROR_DETECTED_BY_DRIVER; \ goto exit; \ } \ } while (0) /** Like #PSA_ASSERT for a PSA API call that calls a driver underneath. * * Run the code \p expr. If this returns \p expected_status, * do nothing. If this returns #PSA_ERROR_DETECTED_BY_DRIVER, * jump directly to the `exit` label. If this returns any other * status, call mbedtls_test_fail() then jump to `exit`. * * The special case for #PSA_ERROR_DETECTED_BY_DRIVER is because in this * case, the test driver code is expected to have called mbedtls_test_fail() * already, so we make sure not to overwrite the failure information. */ #define PSA_ASSERT_VIA_DRIVER(expr, expected_status) \ do { \ psa_status_t PSA_ASSERT_VIA_DRIVER_status = (expr); \ if (PSA_ASSERT_VIA_DRIVER_status == PSA_ERROR_DETECTED_BY_DRIVER) \ goto exit; \ if (PSA_ASSERT_VIA_DRIVER_status != (expected_status)) \ { \ mbedtls_test_fail( #expr, __LINE__, __FILE__); \ goto exit; \ } \ } while (0) /****************************************************************/ /* Domain support functions */ /****************************************************************/ /* Return the exact bit size given a curve family and a byte length. */ static size_t ecc_curve_bits(psa_ecc_family_t curve, size_t data_length) { switch (curve) { case PSA_ECC_FAMILY_SECP_R1: if (data_length == PSA_BYTES_TO_BITS(521)) { return 521; } break; case PSA_ECC_FAMILY_MONTGOMERY: if (data_length == PSA_BYTES_TO_BITS(255)) { return 255; } } /* If not listed above, assume a multiple of 8 bits. */ return PSA_BYTES_TO_BITS(data_length); } /****************************************************************/ /* Miscellaneous driver methods */ /****************************************************************/ typedef struct { psa_key_slot_number_t slot_number; psa_key_creation_method_t method; psa_status_t status; } validate_slot_number_directions_t; static validate_slot_number_directions_t validate_slot_number_directions; /* Validate a choice of slot number as directed. */ static psa_status_t validate_slot_number_as_directed( psa_drv_se_context_t *context, void *persistent_data, const psa_key_attributes_t *attributes, psa_key_creation_method_t method, psa_key_slot_number_t slot_number) { (void) context; (void) persistent_data; (void) attributes; DRIVER_ASSERT_RETURN(slot_number == validate_slot_number_directions.slot_number); DRIVER_ASSERT_RETURN(method == validate_slot_number_directions.method); return validate_slot_number_directions.status; } /* Allocate slot numbers with a monotonic counter. */ static psa_key_slot_number_t shadow_counter; static void counter_reset(void) { shadow_counter = 0; } static psa_status_t counter_allocate(psa_drv_se_context_t *context, void *persistent_data, const psa_key_attributes_t *attributes, psa_key_creation_method_t method, psa_key_slot_number_t *slot_number) { psa_key_slot_number_t *p_counter = persistent_data; (void) attributes; (void) method; if (context->persistent_data_size != sizeof(psa_key_slot_number_t)) { return PSA_ERROR_DETECTED_BY_DRIVER; } ++*p_counter; if (*p_counter == 0) { return PSA_ERROR_INSUFFICIENT_STORAGE; } shadow_counter = *p_counter; *slot_number = *p_counter; return PSA_SUCCESS; } /* Null import: do nothing, but pretend it worked. */ #if defined(AT_LEAST_ONE_BUILTIN_KDF) static psa_status_t null_import(psa_drv_se_context_t *context, psa_key_slot_number_t slot_number, const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, size_t *bits) { (void) context; (void) slot_number; (void) attributes; (void) data; /* We're supposed to return a key size. Return one that's correct for * plain data keys. */ *bits = PSA_BYTES_TO_BITS(data_length); return PSA_SUCCESS; } #endif /* AT_LEAST_ONE_BUILTIN_KDF */ /* Null generate: do nothing, but pretend it worked. */ #if defined(AT_LEAST_ONE_BUILTIN_KDF) static psa_status_t null_generate(psa_drv_se_context_t *context, psa_key_slot_number_t slot_number, const psa_key_attributes_t *attributes, uint8_t *pubkey, size_t pubkey_size, size_t *pubkey_length) { (void) context; (void) slot_number; (void) attributes; DRIVER_ASSERT_RETURN(*pubkey_length == 0); if (!PSA_KEY_TYPE_IS_KEY_PAIR(psa_get_key_type(attributes))) { DRIVER_ASSERT_RETURN(pubkey == NULL); DRIVER_ASSERT_RETURN(pubkey_size == 0); } return PSA_SUCCESS; } #endif /* AT_LEAST_ONE_BUILTIN_KDF */ /* Null destroy: do nothing, but pretend it worked. */ static psa_status_t null_destroy(psa_drv_se_context_t *context, void *persistent_data, psa_key_slot_number_t slot_number) { (void) context; (void) persistent_data; (void) slot_number; return PSA_SUCCESS; } /****************************************************************/ /* RAM-based test driver */ /****************************************************************/ #define RAM_MAX_KEY_SIZE 64 typedef struct { psa_key_lifetime_t lifetime; psa_key_type_t type; size_t bits; uint8_t content[RAM_MAX_KEY_SIZE]; } ram_slot_t; static ram_slot_t ram_slots[16]; /* A type with at least ARRAY_LENGTH(ram_slots) bits, containing a * bit vector indicating which slots are in use. */ typedef uint16_t ram_slot_usage_t; static ram_slot_usage_t ram_shadow_slot_usage; static uint8_t ram_min_slot = 0; static void ram_slots_reset(void) { memset(ram_slots, 0, sizeof(ram_slots)); ram_min_slot = 0; ram_shadow_slot_usage = 0; } /* Common parts of key creation. * * In case of error, zero out ram_slots[slot_number]. But don't * do that if the error is PSA_ERROR_DETECTED_BY_DRIVER: in this case * you don't need to clean up (ram_slot_reset() will take care of it * in the test case function's cleanup code) and it might be wrong * (if slot_number is invalid). */ static psa_status_t ram_create_common(psa_drv_se_context_t *context, psa_key_slot_number_t slot_number, const psa_key_attributes_t *attributes, size_t required_storage) { (void) context; DRIVER_ASSERT_RETURN(slot_number < ARRAY_LENGTH(ram_slots)); ram_slots[slot_number].lifetime = psa_get_key_lifetime(attributes); ram_slots[slot_number].type = psa_get_key_type(attributes); ram_slots[slot_number].bits = psa_get_key_bits(attributes); if (required_storage > sizeof(ram_slots[slot_number].content)) { memset(&ram_slots[slot_number], 0, sizeof(ram_slots[slot_number])); return PSA_ERROR_INSUFFICIENT_STORAGE; } return PSA_SUCCESS; } /* This function does everything except actually generating key material. * After calling it, you must copy the desired key material to * ram_slots[slot_number].content. */ static psa_status_t ram_fake_generate(psa_drv_se_context_t *context, psa_key_slot_number_t slot_number, const psa_key_attributes_t *attributes, uint8_t *pubkey, size_t pubkey_size, size_t *pubkey_length) { psa_status_t status; size_t required_storage = PSA_EXPORT_KEY_OUTPUT_SIZE(psa_get_key_type(attributes), psa_get_key_bits(attributes)); DRIVER_ASSERT_RETURN(*pubkey_length == 0); if (!PSA_KEY_TYPE_IS_KEY_PAIR(psa_get_key_type(attributes))) { DRIVER_ASSERT_RETURN(pubkey == NULL); DRIVER_ASSERT_RETURN(pubkey_size == 0); } status = ram_create_common(context, slot_number, attributes, required_storage); return status; } static psa_status_t ram_import(psa_drv_se_context_t *context, psa_key_slot_number_t slot_number, const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, size_t *bits) { psa_key_type_t type = psa_get_key_type(attributes); psa_status_t status = ram_create_common(context, slot_number, attributes, data_length); if (status != PSA_SUCCESS) { return status; } /* The RAM driver only works for certain key types: raw keys, * and ECC key pairs. This is true in particular of the bit-size * calculation here. */ if (PSA_KEY_TYPE_IS_UNSTRUCTURED(type)) { *bits = PSA_BYTES_TO_BITS(data_length); } else if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) { *bits = ecc_curve_bits(PSA_KEY_TYPE_ECC_GET_FAMILY(type), data_length); if (*bits == 0) { return PSA_ERROR_DETECTED_BY_DRIVER; } } else { memset(&ram_slots[slot_number], 0, sizeof(ram_slots[slot_number])); return PSA_ERROR_NOT_SUPPORTED; } ram_slots[slot_number].bits = *bits; memcpy(ram_slots[slot_number].content, data, data_length); return PSA_SUCCESS; } static psa_status_t ram_export(psa_drv_se_context_t *context, psa_key_slot_number_t slot_number, uint8_t *data, size_t data_size, size_t *data_length) { size_t actual_size; (void) context; DRIVER_ASSERT_RETURN(slot_number < ARRAY_LENGTH(ram_slots)); actual_size = PSA_BITS_TO_BYTES(ram_slots[slot_number].bits); if (actual_size > data_size) { return PSA_ERROR_BUFFER_TOO_SMALL; } *data_length = actual_size; memcpy(data, ram_slots[slot_number].content, actual_size); return PSA_SUCCESS; } static psa_status_t ram_export_public(psa_drv_se_context_t *context, psa_key_slot_number_t slot_number, uint8_t *data, size_t data_size, size_t *data_length) { psa_status_t status; mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; (void) context; DRIVER_ASSERT_RETURN(slot_number < ARRAY_LENGTH(ram_slots)); DRIVER_ASSERT_RETURN( PSA_KEY_TYPE_IS_KEY_PAIR(ram_slots[slot_number].type)); psa_set_key_type(&attributes, ram_slots[slot_number].type); status = psa_import_key(&attributes, ram_slots[slot_number].content, PSA_BITS_TO_BYTES(ram_slots[slot_number].bits), &key); if (status != PSA_SUCCESS) { return status; } status = psa_export_public_key(key, data, data_size, data_length); psa_destroy_key(key); return PSA_SUCCESS; } static psa_status_t ram_destroy(psa_drv_se_context_t *context, void *persistent_data, psa_key_slot_number_t slot_number) { ram_slot_usage_t *slot_usage = persistent_data; DRIVER_ASSERT_RETURN(context->persistent_data_size == sizeof(ram_slot_usage_t)); DRIVER_ASSERT_RETURN(slot_number < ARRAY_LENGTH(ram_slots)); memset(&ram_slots[slot_number], 0, sizeof(ram_slots[slot_number])); *slot_usage &= ~(ram_slot_usage_t) (1 << slot_number); ram_shadow_slot_usage = *slot_usage; return PSA_SUCCESS; } static psa_status_t ram_allocate(psa_drv_se_context_t *context, void *persistent_data, const psa_key_attributes_t *attributes, psa_key_creation_method_t method, psa_key_slot_number_t *slot_number) { ram_slot_usage_t *slot_usage = persistent_data; (void) attributes; (void) method; DRIVER_ASSERT_RETURN(context->persistent_data_size == sizeof(ram_slot_usage_t)); for (*slot_number = ram_min_slot; *slot_number < ARRAY_LENGTH(ram_slots); ++(*slot_number)) { if (!(*slot_usage & 1 << *slot_number)) { ram_shadow_slot_usage = *slot_usage; return PSA_SUCCESS; } } return PSA_ERROR_INSUFFICIENT_STORAGE; } static psa_status_t ram_validate_slot_number( psa_drv_se_context_t *context, void *persistent_data, const psa_key_attributes_t *attributes, psa_key_creation_method_t method, psa_key_slot_number_t slot_number) { (void) context; (void) persistent_data; (void) attributes; (void) method; if (slot_number >= ARRAY_LENGTH(ram_slots)) { return PSA_ERROR_INVALID_ARGUMENT; } return PSA_SUCCESS; } static psa_status_t ram_sign(psa_drv_se_context_t *context, psa_key_slot_number_t slot_number, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, uint8_t *signature, size_t signature_size, size_t *signature_length) { ram_slot_t *slot; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; psa_status_t status = PSA_ERROR_GENERIC_ERROR; (void) context; DRIVER_ASSERT_RETURN(slot_number < ARRAY_LENGTH(ram_slots)); slot = &ram_slots[slot_number]; psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); psa_set_key_algorithm(&attributes, alg); psa_set_key_type(&attributes, slot->type); DRIVER_ASSERT(psa_import_key(&attributes, slot->content, PSA_BITS_TO_BYTES(slot->bits), &key) == PSA_SUCCESS); status = psa_sign_hash(key, alg, hash, hash_length, signature, signature_size, signature_length); exit: psa_destroy_key(key); return status; } static psa_status_t ram_verify(psa_drv_se_context_t *context, psa_key_slot_number_t slot_number, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length) { ram_slot_t *slot; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; psa_status_t status = PSA_ERROR_GENERIC_ERROR; (void) context; DRIVER_ASSERT_RETURN(slot_number < ARRAY_LENGTH(ram_slots)); slot = &ram_slots[slot_number]; psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); psa_set_key_algorithm(&attributes, alg); psa_set_key_type(&attributes, slot->type); DRIVER_ASSERT(psa_import_key(&attributes, slot->content, PSA_BITS_TO_BYTES(slot->bits), &key) == PSA_SUCCESS); status = psa_verify_hash(key, alg, hash, hash_length, signature, signature_length); exit: psa_destroy_key(key); return status; } /****************************************************************/ /* Other test helper functions */ /****************************************************************/ typedef enum { SIGN_IN_SOFTWARE_AND_PARALLEL_CREATION, SIGN_IN_DRIVER_AND_PARALLEL_CREATION, SIGN_IN_DRIVER_THEN_EXPORT_PUBLIC, } sign_verify_method_t; /* Check that the attributes of a key reported by psa_get_key_attributes() * are consistent with the attributes used when creating the key. */ static int check_key_attributes( mbedtls_svc_key_id_t key, const psa_key_attributes_t *reference_attributes) { int ok = 0; psa_key_attributes_t actual_attributes = PSA_KEY_ATTRIBUTES_INIT; PSA_ASSERT(psa_get_key_attributes(key, &actual_attributes)); TEST_ASSERT(mbedtls_svc_key_id_equal( psa_get_key_id(&actual_attributes), psa_get_key_id(reference_attributes))); TEST_EQUAL(psa_get_key_lifetime(&actual_attributes), psa_get_key_lifetime(reference_attributes)); TEST_EQUAL(psa_get_key_type(&actual_attributes), psa_get_key_type(reference_attributes)); TEST_EQUAL(psa_get_key_usage_flags(&actual_attributes), psa_get_key_usage_flags(reference_attributes)); TEST_EQUAL(psa_get_key_algorithm(&actual_attributes), psa_get_key_algorithm(reference_attributes)); TEST_EQUAL(psa_get_key_enrollment_algorithm(&actual_attributes), psa_get_key_enrollment_algorithm(reference_attributes)); if (psa_get_key_bits(reference_attributes) != 0) { TEST_EQUAL(psa_get_key_bits(&actual_attributes), psa_get_key_bits(reference_attributes)); } { psa_key_slot_number_t actual_slot_number = 0xdeadbeef; psa_key_slot_number_t desired_slot_number = 0xb90cc011; psa_key_lifetime_t lifetime = psa_get_key_lifetime(&actual_attributes); psa_status_t status = psa_get_key_slot_number(&actual_attributes, &actual_slot_number); if (PSA_KEY_LIFETIME_GET_LOCATION(lifetime) < MIN_DRIVER_LOCATION) { /* The key is not in a secure element. */ TEST_EQUAL(status, PSA_ERROR_INVALID_ARGUMENT); } else { /* The key is in a secure element. If it had been created * in a specific slot, check that it is reported there. */ PSA_ASSERT(status); status = psa_get_key_slot_number(reference_attributes, &desired_slot_number); if (status == PSA_SUCCESS) { TEST_EQUAL(desired_slot_number, actual_slot_number); } } } ok = 1; exit: /* * Actual key attributes may have been returned by psa_get_key_attributes() * thus reset them as required. */ psa_reset_key_attributes(&actual_attributes); return ok; } /* Get the file UID corresponding to the specified location. * If this changes, the storage format version must change. * See psa_get_se_driver_its_file_uid() in psa_crypto_se.c. */ psa_storage_uid_t file_uid_for_location(psa_key_location_t location) { if (location > PSA_MAX_SE_LOCATION) { return 0; } return 0xfffffe00 + location; } /* Check that the persistent data of a driver has its expected content. */ static int check_persistent_data(psa_key_location_t location, const void *expected_data, size_t size) { psa_storage_uid_t uid = file_uid_for_location(location); struct psa_storage_info_t info; uint8_t *loaded = NULL; int ok = 0; PSA_ASSERT(psa_its_get_info(uid, &info)); TEST_CALLOC_OR_FAIL(loaded, info.size); PSA_ASSERT(psa_its_get(uid, 0, info.size, loaded, NULL)); TEST_BUFFERS_EQUAL(expected_data, size, loaded, info.size); ok = 1; exit: mbedtls_free(loaded); return ok; } /* Check that no persistent data exists for the given location. */ static int check_no_persistent_data(psa_key_location_t location) { psa_storage_uid_t uid = file_uid_for_location(location); struct psa_storage_info_t info; int ok = 0; TEST_EQUAL(psa_its_get_info(uid, &info), PSA_ERROR_DOES_NOT_EXIST); ok = 1; exit: return ok; } /* Check that a function's return status is "smoke-free", i.e. that * it's an acceptable error code when calling an API function that operates * on a key with potentially bogus parameters. */ #if defined(AT_LEAST_ONE_BUILTIN_KDF) static int is_status_smoke_free(psa_status_t status) { switch (status) { case PSA_SUCCESS: case PSA_ERROR_NOT_SUPPORTED: case PSA_ERROR_NOT_PERMITTED: case PSA_ERROR_BUFFER_TOO_SMALL: case PSA_ERROR_INVALID_ARGUMENT: case PSA_ERROR_INVALID_SIGNATURE: case PSA_ERROR_INVALID_PADDING: return 1; default: return 0; } } #endif /* AT_LEAST_ONE_BUILTIN_KDF */ #define SMOKE_ASSERT(expr) \ TEST_ASSERT(is_status_smoke_free(expr)) /* Smoke test a key. There are mostly no wrong answers here since we pass * mostly bogus parameters: the goal is to ensure that there is no memory * corruption or crash. This test function is most useful when run under * an environment with sanity checks such as ASan or MSan. */ #if defined(AT_LEAST_ONE_BUILTIN_KDF) static int smoke_test_key(mbedtls_svc_key_id_t key) { int ok = 0; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_mac_operation_t mac_operation = PSA_MAC_OPERATION_INIT; psa_cipher_operation_t cipher_operation = PSA_CIPHER_OPERATION_INIT; psa_key_derivation_operation_t derivation_operation = PSA_KEY_DERIVATION_OPERATION_INIT; uint8_t buffer[80]; /* large enough for a public key for ECDH */ size_t length; mbedtls_svc_key_id_t key2 = MBEDTLS_SVC_KEY_ID_INIT; SMOKE_ASSERT(psa_get_key_attributes(key, &attributes)); SMOKE_ASSERT(psa_export_key(key, buffer, sizeof(buffer), &length)); SMOKE_ASSERT(psa_export_public_key(key, buffer, sizeof(buffer), &length)); SMOKE_ASSERT(psa_copy_key(key, &attributes, &key2)); if (!mbedtls_svc_key_id_is_null(key2)) { PSA_ASSERT(psa_destroy_key(key2)); } SMOKE_ASSERT(psa_mac_sign_setup(&mac_operation, key, PSA_ALG_CMAC)); PSA_ASSERT(psa_mac_abort(&mac_operation)); SMOKE_ASSERT(psa_mac_verify_setup(&mac_operation, key, PSA_ALG_HMAC(PSA_ALG_SHA_256))); PSA_ASSERT(psa_mac_abort(&mac_operation)); SMOKE_ASSERT(psa_cipher_encrypt_setup(&cipher_operation, key, PSA_ALG_CTR)); PSA_ASSERT(psa_cipher_abort(&cipher_operation)); SMOKE_ASSERT(psa_cipher_decrypt_setup(&cipher_operation, key, PSA_ALG_CTR)); PSA_ASSERT(psa_cipher_abort(&cipher_operation)); SMOKE_ASSERT(psa_aead_encrypt(key, PSA_ALG_CCM, buffer, sizeof(buffer), NULL, 0, buffer, sizeof(buffer), buffer, sizeof(buffer), &length)); SMOKE_ASSERT(psa_aead_decrypt(key, PSA_ALG_CCM, buffer, sizeof(buffer), NULL, 0, buffer, sizeof(buffer), buffer, sizeof(buffer), &length)); SMOKE_ASSERT(psa_sign_hash(key, PSA_ALG_ECDSA_ANY, buffer, 32, buffer, sizeof(buffer), &length)); SMOKE_ASSERT(psa_verify_hash(key, PSA_ALG_ECDSA_ANY, buffer, 32, buffer, sizeof(buffer))); SMOKE_ASSERT(psa_asymmetric_encrypt(key, PSA_ALG_RSA_PKCS1V15_CRYPT, buffer, 10, NULL, 0, buffer, sizeof(buffer), &length)); SMOKE_ASSERT(psa_asymmetric_decrypt(key, PSA_ALG_RSA_PKCS1V15_CRYPT, buffer, sizeof(buffer), NULL, 0, buffer, sizeof(buffer), &length)); #if defined(PSA_WANT_ALG_SHA_256) /* Try the key in a plain key derivation. */ PSA_ASSERT(psa_key_derivation_setup(&derivation_operation, PSA_ALG_HKDF(PSA_ALG_SHA_256))); PSA_ASSERT(psa_key_derivation_input_bytes(&derivation_operation, PSA_KEY_DERIVATION_INPUT_SALT, NULL, 0)); SMOKE_ASSERT(psa_key_derivation_input_key(&derivation_operation, PSA_KEY_DERIVATION_INPUT_SECRET, key)); PSA_ASSERT(psa_key_derivation_abort(&derivation_operation)); /* If the key is asymmetric, try it in a key agreement, both as * part of a derivation operation and standalone. */ if (psa_export_public_key(key, buffer, sizeof(buffer), &length) == PSA_SUCCESS) { psa_algorithm_t alg = PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)); PSA_ASSERT(psa_key_derivation_setup(&derivation_operation, alg)); PSA_ASSERT(psa_key_derivation_input_bytes( &derivation_operation, PSA_KEY_DERIVATION_INPUT_SALT, NULL, 0)); SMOKE_ASSERT(psa_key_derivation_key_agreement( &derivation_operation, PSA_KEY_DERIVATION_INPUT_SECRET, key, buffer, length)); PSA_ASSERT(psa_key_derivation_abort(&derivation_operation)); SMOKE_ASSERT(psa_raw_key_agreement( alg, key, buffer, length, buffer, sizeof(buffer), &length)); } #endif /* PSA_WANT_ALG_SHA_256 */ ok = 1; exit: /* * Key attributes may have been returned by psa_get_key_attributes() * thus reset them as required. */ psa_reset_key_attributes(&attributes); return ok; } #endif /* AT_LEAST_ONE_BUILTIN_KDF */ static void psa_purge_storage(void) { /* The generic code in mbedtls_test_psa_purge_key_storage() * (which is called by PSA_DONE()) doesn't take care of things that are * specific to dynamic secure elements. */ psa_key_location_t location; /* Purge the transaction file. */ psa_crypto_stop_transaction(); /* Purge driver persistent data. */ for (location = 0; location < PSA_MAX_SE_LOCATION; location++) { psa_destroy_se_persistent_data(location); } } /* END_HEADER */ /* BEGIN_DEPENDENCIES * depends_on:MBEDTLS_PSA_CRYPTO_SE_C * END_DEPENDENCIES */ /* BEGIN_CASE */ void register_one(int location, int version, int expected_status_arg) { psa_status_t expected_status = expected_status_arg; psa_drv_se_t driver; memset(&driver, 0, sizeof(driver)); driver.hal_version = version; TEST_EQUAL(psa_register_se_driver(location, &driver), expected_status); PSA_ASSERT(psa_crypto_init()); exit: PSA_DONE(); } /* END_CASE */ /* BEGIN_CASE */ void register_twice(int count) { psa_drv_se_t driver; psa_key_location_t location; psa_key_location_t max = MIN_DRIVER_LOCATION + count; memset(&driver, 0, sizeof(driver)); driver.hal_version = PSA_DRV_SE_HAL_VERSION; for (location = MIN_DRIVER_LOCATION; location < max; location++) { PSA_ASSERT(psa_register_se_driver(location, &driver)); } for (location = MIN_DRIVER_LOCATION; location < max; location++) { TEST_EQUAL(psa_register_se_driver(location, &driver), PSA_ERROR_ALREADY_EXISTS); } PSA_ASSERT(psa_crypto_init()); exit: PSA_DONE(); } /* END_CASE */ /* BEGIN_CASE */ void register_max() { psa_drv_se_t driver; psa_key_location_t location; psa_key_location_t max = MIN_DRIVER_LOCATION + PSA_MAX_SE_DRIVERS; memset(&driver, 0, sizeof(driver)); driver.hal_version = PSA_DRV_SE_HAL_VERSION; for (location = MIN_DRIVER_LOCATION; location < max; location++) { PSA_ASSERT(psa_register_se_driver(location, &driver)); } TEST_EQUAL(psa_register_se_driver(location, &driver), PSA_ERROR_INSUFFICIENT_MEMORY); PSA_ASSERT(psa_crypto_init()); exit: PSA_DONE(); } /* END_CASE */ /* BEGIN_CASE */ void key_creation_import_export(int lifetime_arg, int min_slot, int restart) { psa_drv_se_t driver; psa_drv_se_key_management_t key_management; psa_key_lifetime_t lifetime = (psa_key_lifetime_t) lifetime_arg; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(lifetime); mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make(1, 1); mbedtls_svc_key_id_t returned_id = MBEDTLS_SVC_KEY_ID_INIT; psa_key_handle_t handle; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; const uint8_t key_material[3] = { 0xfa, 0xca, 0xde }; uint8_t exported[sizeof(key_material)]; size_t exported_length; TEST_USES_KEY_ID(id); memset(&driver, 0, sizeof(driver)); memset(&key_management, 0, sizeof(key_management)); driver.hal_version = PSA_DRV_SE_HAL_VERSION; driver.key_management = &key_management; driver.persistent_data_size = sizeof(ram_slot_usage_t); key_management.p_allocate = ram_allocate; key_management.p_import = ram_import; key_management.p_destroy = ram_destroy; key_management.p_export = ram_export; ram_min_slot = min_slot; PSA_ASSERT(psa_register_se_driver(location, &driver)); PSA_ASSERT(psa_crypto_init()); /* Create a key. */ psa_set_key_id(&attributes, id); psa_set_key_lifetime(&attributes, lifetime); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT); psa_set_key_type(&attributes, PSA_KEY_TYPE_RAW_DATA); PSA_ASSERT(psa_import_key(&attributes, key_material, sizeof(key_material), &returned_id)); if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) { /* For volatile keys, check no persistent data was created */ if (!check_no_persistent_data(location)) { goto exit; } } else { /* For persistent keys, check persistent data */ if (!check_persistent_data(location, &ram_shadow_slot_usage, sizeof(ram_shadow_slot_usage))) { goto exit; } } /* Test that the key was created in the expected slot. */ TEST_EQUAL(ram_slots[min_slot].type, PSA_KEY_TYPE_RAW_DATA); /* Maybe restart, to check that the information is saved correctly. */ if (restart) { mbedtls_psa_crypto_free(); PSA_ASSERT(psa_register_se_driver(location, &driver)); PSA_ASSERT(psa_crypto_init()); if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) { /* Check that the PSA core has no knowledge of the volatile key */ TEST_ASSERT(psa_open_key(returned_id, &handle) == PSA_ERROR_DOES_NOT_EXIST); /* Drop data from our mockup driver */ ram_slots_reset(); ram_min_slot = min_slot; /* Re-import key */ PSA_ASSERT(psa_import_key(&attributes, key_material, sizeof(key_material), &returned_id)); } else { /* Check the persistent key file */ if (!check_persistent_data(location, &ram_shadow_slot_usage, sizeof(ram_shadow_slot_usage))) { goto exit; } } } /* Test that the key was created in the expected slot. */ TEST_EQUAL(ram_slots[min_slot].type, PSA_KEY_TYPE_RAW_DATA); /* Test the key attributes, including the reported slot number. */ psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(sizeof(key_material))); psa_set_key_slot_number(&attributes, min_slot); if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) { attributes.core.id = returned_id; } else { psa_set_key_id(&attributes, returned_id); } if (!check_key_attributes(returned_id, &attributes)) { goto exit; } /* Test the key data. */ PSA_ASSERT(psa_export_key(returned_id, exported, sizeof(exported), &exported_length)); TEST_BUFFERS_EQUAL(key_material, sizeof(key_material), exported, exported_length); PSA_ASSERT(psa_destroy_key(returned_id)); if (!check_persistent_data(location, &ram_shadow_slot_usage, sizeof(ram_shadow_slot_usage))) { goto exit; } TEST_EQUAL(psa_open_key(returned_id, &handle), PSA_ERROR_DOES_NOT_EXIST); /* Test that the key has been erased from the designated slot. */ TEST_EQUAL(ram_slots[min_slot].type, 0); exit: PSA_DONE(); ram_slots_reset(); psa_purge_storage(); } /* END_CASE */ /* BEGIN_CASE */ void key_creation_in_chosen_slot(int slot_arg, int restart, int expected_status_arg) { psa_key_slot_number_t wanted_slot = slot_arg; psa_status_t expected_status = expected_status_arg; psa_status_t status; psa_drv_se_t driver; psa_drv_se_key_management_t key_management; psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(lifetime); mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make(1, 1); mbedtls_svc_key_id_t returned_id; psa_key_handle_t handle; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; const uint8_t key_material[3] = { 0xfa, 0xca, 0xde }; TEST_USES_KEY_ID(id); memset(&driver, 0, sizeof(driver)); memset(&key_management, 0, sizeof(key_management)); driver.hal_version = PSA_DRV_SE_HAL_VERSION; driver.key_management = &key_management; driver.persistent_data_size = sizeof(ram_slot_usage_t); key_management.p_validate_slot_number = ram_validate_slot_number; key_management.p_import = ram_import; key_management.p_destroy = ram_destroy; key_management.p_export = ram_export; PSA_ASSERT(psa_register_se_driver(location, &driver)); PSA_ASSERT(psa_crypto_init()); /* Create a key. */ psa_set_key_id(&attributes, id); psa_set_key_lifetime(&attributes, lifetime); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT); psa_set_key_type(&attributes, PSA_KEY_TYPE_RAW_DATA); psa_set_key_slot_number(&attributes, wanted_slot); status = psa_import_key(&attributes, key_material, sizeof(key_material), &returned_id); TEST_EQUAL(status, expected_status); if (status != PSA_SUCCESS) { goto exit; } if (!check_persistent_data(location, &ram_shadow_slot_usage, sizeof(ram_shadow_slot_usage))) { goto exit; } /* Maybe restart, to check that the information is saved correctly. */ if (restart) { mbedtls_psa_crypto_free(); PSA_ASSERT(psa_register_se_driver(location, &driver)); PSA_ASSERT(psa_crypto_init()); if (!check_persistent_data(location, &ram_shadow_slot_usage, sizeof(ram_shadow_slot_usage))) { goto exit; } } /* Test that the key was created in the expected slot. */ TEST_EQUAL(ram_slots[wanted_slot].type, PSA_KEY_TYPE_RAW_DATA); /* Test that the key is reported with the correct attributes, * including the expected slot. */ PSA_ASSERT(psa_get_key_attributes(id, &attributes)); PSA_ASSERT(psa_destroy_key(id)); if (!check_persistent_data(location, &ram_shadow_slot_usage, sizeof(ram_shadow_slot_usage))) { goto exit; } TEST_EQUAL(psa_open_key(id, &handle), PSA_ERROR_DOES_NOT_EXIST); exit: /* * Key attributes may have been returned by psa_get_key_attributes() * thus reset them as required. */ psa_reset_key_attributes(&attributes); PSA_DONE(); ram_slots_reset(); psa_purge_storage(); } /* END_CASE */ /* BEGIN_CASE depends_on:AT_LEAST_ONE_BUILTIN_KDF */ void import_key_smoke(int type_arg, int alg_arg, data_t *key_material) { psa_key_type_t type = type_arg; psa_algorithm_t alg = alg_arg; psa_drv_se_t driver; psa_drv_se_key_management_t key_management; psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(lifetime); mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make(1, 1); mbedtls_svc_key_id_t returned_id; psa_key_handle_t handle; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; TEST_USES_KEY_ID(id); memset(&driver, 0, sizeof(driver)); memset(&key_management, 0, sizeof(key_management)); driver.hal_version = PSA_DRV_SE_HAL_VERSION; driver.key_management = &key_management; driver.persistent_data_size = sizeof(psa_key_slot_number_t); key_management.p_allocate = counter_allocate; key_management.p_import = null_import; key_management.p_destroy = null_destroy; PSA_ASSERT(psa_register_se_driver(location, &driver)); PSA_ASSERT(psa_crypto_init()); /* Create a key. */ psa_set_key_id(&attributes, id); psa_set_key_lifetime(&attributes, lifetime); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT); psa_set_key_algorithm(&attributes, alg); psa_set_key_type(&attributes, type); PSA_ASSERT(psa_import_key(&attributes, key_material->x, key_material->len, &returned_id)); if (!check_persistent_data(location, &shadow_counter, sizeof(shadow_counter))) { goto exit; } /* Do stuff with the key. */ if (!smoke_test_key(id)) { goto exit; } /* Restart and try again. */ mbedtls_psa_crypto_free(); PSA_ASSERT(psa_register_se_driver(location, &driver)); PSA_ASSERT(psa_crypto_init()); if (!check_persistent_data(location, &shadow_counter, sizeof(shadow_counter))) { goto exit; } if (!smoke_test_key(id)) { goto exit; } /* We're done. */ PSA_ASSERT(psa_destroy_key(id)); if (!check_persistent_data(location, &shadow_counter, sizeof(shadow_counter))) { goto exit; } TEST_EQUAL(psa_open_key(id, &handle), PSA_ERROR_DOES_NOT_EXIST); exit: PSA_DONE(); counter_reset(); psa_purge_storage(); } /* END_CASE */ /* BEGIN_CASE */ void generate_key_not_supported(int type_arg, int bits_arg) { psa_key_type_t type = type_arg; size_t bits = bits_arg; psa_drv_se_t driver; psa_drv_se_key_management_t key_management; psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(lifetime); mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make(1, 1); mbedtls_svc_key_id_t returned_id; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; TEST_USES_KEY_ID(id); memset(&driver, 0, sizeof(driver)); memset(&key_management, 0, sizeof(key_management)); driver.hal_version = PSA_DRV_SE_HAL_VERSION; driver.key_management = &key_management; driver.persistent_data_size = sizeof(psa_key_slot_number_t); key_management.p_allocate = counter_allocate; /* No p_generate method */ PSA_ASSERT(psa_register_se_driver(location, &driver)); PSA_ASSERT(psa_crypto_init()); psa_set_key_id(&attributes, id); psa_set_key_lifetime(&attributes, lifetime); psa_set_key_type(&attributes, type); psa_set_key_bits(&attributes, bits); TEST_EQUAL(psa_generate_key(&attributes, &returned_id), PSA_ERROR_NOT_SUPPORTED); exit: PSA_DONE(); counter_reset(); psa_purge_storage(); } /* END_CASE */ /* BEGIN_CASE depends_on:AT_LEAST_ONE_BUILTIN_KDF */ void generate_key_smoke(int type_arg, int bits_arg, int alg_arg) { psa_key_type_t type = type_arg; psa_key_bits_t bits = bits_arg; psa_algorithm_t alg = alg_arg; psa_drv_se_t driver; psa_drv_se_key_management_t key_management; psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(lifetime); mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make(1, 1); mbedtls_svc_key_id_t returned_id; psa_key_handle_t handle; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; TEST_USES_KEY_ID(id); memset(&driver, 0, sizeof(driver)); memset(&key_management, 0, sizeof(key_management)); driver.hal_version = PSA_DRV_SE_HAL_VERSION; driver.key_management = &key_management; driver.persistent_data_size = sizeof(psa_key_slot_number_t); key_management.p_allocate = counter_allocate; key_management.p_generate = null_generate; key_management.p_destroy = null_destroy; PSA_ASSERT(psa_register_se_driver(location, &driver)); PSA_ASSERT(psa_crypto_init()); /* Create a key. */ psa_set_key_id(&attributes, id); psa_set_key_lifetime(&attributes, lifetime); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT); psa_set_key_algorithm(&attributes, alg); psa_set_key_type(&attributes, type); psa_set_key_bits(&attributes, bits); PSA_ASSERT(psa_generate_key(&attributes, &returned_id)); if (!check_persistent_data(location, &shadow_counter, sizeof(shadow_counter))) { goto exit; } /* Do stuff with the key. */ if (!smoke_test_key(id)) { goto exit; } /* Restart and try again. */ mbedtls_psa_crypto_free(); PSA_ASSERT(psa_register_se_driver(location, &driver)); PSA_ASSERT(psa_crypto_init()); if (!check_persistent_data(location, &shadow_counter, sizeof(shadow_counter))) { goto exit; } if (!smoke_test_key(id)) { goto exit; } /* We're done. */ PSA_ASSERT(psa_destroy_key(id)); if (!check_persistent_data(location, &shadow_counter, sizeof(shadow_counter))) { goto exit; } TEST_EQUAL(psa_open_key(id, &handle), PSA_ERROR_DOES_NOT_EXIST); exit: PSA_DONE(); counter_reset(); psa_purge_storage(); } /* END_CASE */ /* BEGIN_CASE */ void sign_verify(int flow, int type_arg, int alg_arg, int bits_arg, data_t *key_material, data_t *input) { psa_key_type_t type = type_arg; psa_algorithm_t alg = alg_arg; size_t bits = bits_arg; /* Pass bits=0 to import, bits>0 to fake-generate */ int generating = (bits != 0); psa_drv_se_t driver; psa_drv_se_key_management_t key_management; psa_drv_se_asymmetric_t asymmetric; psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(lifetime); mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make(1, 1); mbedtls_svc_key_id_t returned_id; mbedtls_svc_key_id_t sw_key = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t sw_attributes = PSA_KEY_ATTRIBUTES_INIT; psa_key_attributes_t drv_attributes; uint8_t signature[PSA_SIGNATURE_MAX_SIZE]; size_t signature_length; TEST_USES_KEY_ID(id); memset(&driver, 0, sizeof(driver)); memset(&key_management, 0, sizeof(key_management)); memset(&asymmetric, 0, sizeof(asymmetric)); driver.hal_version = PSA_DRV_SE_HAL_VERSION; driver.key_management = &key_management; driver.asymmetric = &asymmetric; driver.persistent_data_size = sizeof(ram_slot_usage_t); key_management.p_allocate = ram_allocate; key_management.p_destroy = ram_destroy; if (generating) { key_management.p_generate = ram_fake_generate; } else { key_management.p_import = ram_import; } switch (flow) { case SIGN_IN_SOFTWARE_AND_PARALLEL_CREATION: break; case SIGN_IN_DRIVER_AND_PARALLEL_CREATION: asymmetric.p_sign = ram_sign; break; case SIGN_IN_DRIVER_THEN_EXPORT_PUBLIC: asymmetric.p_sign = ram_sign; key_management.p_export_public = ram_export_public; break; default: TEST_ASSERT(!"unsupported flow (should be SIGN_IN_xxx)"); break; } asymmetric.p_verify = ram_verify; PSA_ASSERT(psa_register_se_driver(location, &driver)); PSA_ASSERT(psa_crypto_init()); /* Prepare to create two keys with the same key material: a transparent * key, and one that goes through the driver. */ psa_set_key_usage_flags(&sw_attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH); psa_set_key_algorithm(&sw_attributes, alg); psa_set_key_type(&sw_attributes, type); drv_attributes = sw_attributes; psa_set_key_id(&drv_attributes, id); psa_set_key_lifetime(&drv_attributes, lifetime); /* Create the key in the driver. */ if (generating) { psa_set_key_bits(&drv_attributes, bits); PSA_ASSERT(psa_generate_key(&drv_attributes, &returned_id)); /* Since we called a generate method that does not actually * generate material, store the desired result of generation in * the mock secure element storage. */ PSA_ASSERT(psa_get_key_attributes(id, &drv_attributes)); TEST_EQUAL(key_material->len, PSA_BITS_TO_BYTES(bits)); memcpy(ram_slots[ram_min_slot].content, key_material->x, key_material->len); } else { PSA_ASSERT(psa_import_key(&drv_attributes, key_material->x, key_material->len, &returned_id)); } /* Either import the same key in software, or export the driver's * public key and import that. */ switch (flow) { case SIGN_IN_SOFTWARE_AND_PARALLEL_CREATION: case SIGN_IN_DRIVER_AND_PARALLEL_CREATION: PSA_ASSERT(psa_import_key(&sw_attributes, key_material->x, key_material->len, &sw_key)); break; case SIGN_IN_DRIVER_THEN_EXPORT_PUBLIC: { uint8_t public_key[PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) ]; size_t public_key_length; PSA_ASSERT(psa_export_public_key(id, public_key, sizeof(public_key), &public_key_length)); psa_set_key_type(&sw_attributes, PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type)); PSA_ASSERT(psa_import_key(&sw_attributes, public_key, public_key_length, &sw_key)); break; } } /* Sign with the chosen key. */ switch (flow) { case SIGN_IN_DRIVER_AND_PARALLEL_CREATION: case SIGN_IN_DRIVER_THEN_EXPORT_PUBLIC: PSA_ASSERT_VIA_DRIVER( psa_sign_hash(id, alg, input->x, input->len, signature, sizeof(signature), &signature_length), PSA_SUCCESS); break; case SIGN_IN_SOFTWARE_AND_PARALLEL_CREATION: PSA_ASSERT(psa_sign_hash(sw_key, alg, input->x, input->len, signature, sizeof(signature), &signature_length)); break; } /* Verify with both keys. */ PSA_ASSERT(psa_verify_hash(sw_key, alg, input->x, input->len, signature, signature_length)); PSA_ASSERT_VIA_DRIVER( psa_verify_hash(id, alg, input->x, input->len, signature, signature_length), PSA_SUCCESS); /* Change the signature and verify again. */ signature[0] ^= 1; TEST_EQUAL(psa_verify_hash(sw_key, alg, input->x, input->len, signature, signature_length), PSA_ERROR_INVALID_SIGNATURE); PSA_ASSERT_VIA_DRIVER( psa_verify_hash(id, alg, input->x, input->len, signature, signature_length), PSA_ERROR_INVALID_SIGNATURE); exit: /* * Driver key attributes may have been returned by psa_get_key_attributes() * thus reset them as required. */ psa_reset_key_attributes(&drv_attributes); psa_destroy_key(id); psa_destroy_key(sw_key); PSA_DONE(); ram_slots_reset(); psa_purge_storage(); } /* END_CASE */ /* BEGIN_CASE */ void register_key_smoke_test(int lifetime_arg, int owner_id_arg, int id_arg, int validate, int expected_status_arg) { psa_key_lifetime_t lifetime = lifetime_arg; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(lifetime); psa_status_t expected_status = expected_status_arg; psa_drv_se_t driver; psa_drv_se_key_management_t key_management; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make(owner_id_arg, id_arg); psa_key_handle_t handle; size_t bit_size = 48; psa_key_slot_number_t wanted_slot = 0x123456789; psa_status_t status; TEST_USES_KEY_ID(id); memset(&driver, 0, sizeof(driver)); driver.hal_version = PSA_DRV_SE_HAL_VERSION; memset(&key_management, 0, sizeof(key_management)); driver.key_management = &key_management; key_management.p_destroy = null_destroy; if (validate >= 0) { key_management.p_validate_slot_number = validate_slot_number_as_directed; validate_slot_number_directions.slot_number = wanted_slot; validate_slot_number_directions.method = PSA_KEY_CREATION_REGISTER; validate_slot_number_directions.status = (validate > 0 ? PSA_SUCCESS : PSA_ERROR_NOT_PERMITTED); } mbedtls_test_set_step(1); PSA_ASSERT(psa_register_se_driver(MIN_DRIVER_LOCATION, &driver)); PSA_ASSERT(psa_crypto_init()); psa_set_key_id(&attributes, id); psa_set_key_lifetime(&attributes, lifetime); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT); psa_set_key_type(&attributes, PSA_KEY_TYPE_RAW_DATA); psa_set_key_bits(&attributes, bit_size); psa_set_key_slot_number(&attributes, wanted_slot); status = mbedtls_psa_register_se_key(&attributes); TEST_EQUAL(status, expected_status); if (status != PSA_SUCCESS) { goto exit; } /* Test that the key exists and has the expected attributes. */ if (!check_key_attributes(id, &attributes)) { goto exit; } #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) mbedtls_svc_key_id_t invalid_id = mbedtls_svc_key_id_make(owner_id_arg + 1, id_arg); TEST_EQUAL(psa_open_key(invalid_id, &handle), PSA_ERROR_DOES_NOT_EXIST); #endif PSA_ASSERT(psa_purge_key(id)); /* Restart and try again. */ mbedtls_test_set_step(2); PSA_SESSION_DONE(); PSA_ASSERT(psa_register_se_driver(location, &driver)); PSA_ASSERT(psa_crypto_init()); if (!check_key_attributes(id, &attributes)) { goto exit; } /* This time, destroy the key. */ PSA_ASSERT(psa_destroy_key(id)); TEST_EQUAL(psa_open_key(id, &handle), PSA_ERROR_DOES_NOT_EXIST); exit: psa_reset_key_attributes(&attributes); psa_destroy_key(id); PSA_DONE(); psa_purge_storage(); memset(&validate_slot_number_directions, 0, sizeof(validate_slot_number_directions)); } /* END_CASE */