/* BEGIN_HEADER */ #include #include "psa_crypto_slot_management.h" #include "psa_crypto_storage.h" typedef enum { /**< Close key(s) */ INVALIDATE_BY_CLOSING, /**< Destroy key(s) */ INVALIDATE_BY_DESTROYING, /**< Purge key(s) */ INVALIDATE_BY_PURGING, /**< Terminate and reinitialize without closing/destroying keys */ INVALIDATE_BY_SHUTDOWN, /**< Close key(s) then terminate and re-initialize */ INVALIDATE_BY_CLOSING_WITH_SHUTDOWN, /**< Destroy key(s) then terminate and re-initialize */ INVALIDATE_BY_DESTROYING_WITH_SHUTDOWN, /**< Purge key(s) then terminate and re-initialize */ INVALIDATE_BY_PURGING_WITH_SHUTDOWN, } invalidate_method_t; typedef enum { KEEP_OPEN, CLOSE_BEFORE, CLOSE_AFTER, } reopen_policy_t; typedef enum { INVALID_HANDLE_0, INVALID_HANDLE_UNOPENED, INVALID_HANDLE_CLOSED, INVALID_HANDLE_HUGE, } invalid_handle_construction_t; /** Apply \p invalidate_method to invalidate the specified key: * close it, destroy it, or do nothing; */ static int invalidate_key(invalidate_method_t invalidate_method, mbedtls_svc_key_id_t key) { switch (invalidate_method) { /* Closing the key invalidate only volatile keys, not persistent ones. */ case INVALIDATE_BY_CLOSING: case INVALIDATE_BY_CLOSING_WITH_SHUTDOWN: PSA_ASSERT(psa_close_key(key)); break; case INVALIDATE_BY_DESTROYING: case INVALIDATE_BY_DESTROYING_WITH_SHUTDOWN: PSA_ASSERT(psa_destroy_key(key)); break; /* Purging the key just purges RAM data of persistent keys. */ case INVALIDATE_BY_PURGING: case INVALIDATE_BY_PURGING_WITH_SHUTDOWN: PSA_ASSERT(psa_purge_key(key)); break; case INVALIDATE_BY_SHUTDOWN: break; } return 1; exit: return 0; } /** Restart the PSA subsystem if \p invalidate_method says so. */ static int invalidate_psa(invalidate_method_t invalidate_method) { switch (invalidate_method) { case INVALIDATE_BY_CLOSING: case INVALIDATE_BY_DESTROYING: case INVALIDATE_BY_PURGING: return 1; case INVALIDATE_BY_CLOSING_WITH_SHUTDOWN: case INVALIDATE_BY_DESTROYING_WITH_SHUTDOWN: case INVALIDATE_BY_PURGING_WITH_SHUTDOWN: /* All keys must have been closed. */ PSA_SESSION_DONE(); break; case INVALIDATE_BY_SHUTDOWN: /* Some keys may remain behind, and we're testing that this * properly closes them. */ mbedtls_psa_crypto_free(); break; } PSA_ASSERT(psa_crypto_init()); ASSERT_PSA_PRISTINE(); return 1; exit: return 0; } /* END_HEADER */ /* BEGIN_DEPENDENCIES * depends_on:MBEDTLS_PSA_CRYPTO_C * END_DEPENDENCIES */ /* BEGIN_CASE */ void transient_slot_lifecycle(int owner_id_arg, int usage_arg, int alg_arg, int type_arg, data_t *key_data, int invalidate_method_arg) { psa_algorithm_t alg = alg_arg; psa_key_usage_t usage_flags = usage_arg; psa_key_type_t type = type_arg; invalidate_method_t invalidate_method = invalidate_method_arg; mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; mbedtls_test_set_step(1); PSA_ASSERT(psa_crypto_init()); /* Import a key. */ #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) mbedtls_key_owner_id_t owner_id = owner_id_arg; mbedtls_set_key_owner_id(&attributes, owner_id); #else (void) owner_id_arg; #endif psa_set_key_usage_flags(&attributes, usage_flags); psa_set_key_algorithm(&attributes, alg); psa_set_key_type(&attributes, type); PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len, &key)); TEST_ASSERT(!mbedtls_svc_key_id_is_null(key)); PSA_ASSERT(psa_get_key_attributes(key, &attributes)); TEST_EQUAL(psa_get_key_type(&attributes), type); psa_reset_key_attributes(&attributes); #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) { mbedtls_svc_key_id_t key_with_invalid_owner = mbedtls_svc_key_id_make(owner_id + 1, MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key)); TEST_ASSERT(mbedtls_key_owner_id_equal( owner_id, MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(key))); TEST_EQUAL(psa_get_key_attributes(key_with_invalid_owner, &attributes), PSA_ERROR_INVALID_HANDLE); } #endif /* * Purge the key and make sure that it is still valid, as purging a * volatile key shouldn't invalidate/destroy it. */ PSA_ASSERT(psa_purge_key(key)); PSA_ASSERT(psa_get_key_attributes(key, &attributes)); TEST_EQUAL(psa_get_key_type(&attributes), type); psa_reset_key_attributes(&attributes); /* Do something that invalidates the key. */ mbedtls_test_set_step(2); if (!invalidate_key(invalidate_method, key)) { goto exit; } if (!invalidate_psa(invalidate_method)) { goto exit; } /* Test that the key is now invalid. */ TEST_EQUAL(psa_get_key_attributes(key, &attributes), PSA_ERROR_INVALID_HANDLE); TEST_EQUAL(psa_close_key(key), PSA_ERROR_INVALID_HANDLE); exit: /* * Key attributes may have been returned by psa_get_key_attributes() * thus reset them as required. */ psa_reset_key_attributes(&attributes); PSA_DONE(); } /* END_CASE */ /* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C */ void persistent_slot_lifecycle(int lifetime_arg, int owner_id_arg, int id_arg, int usage_arg, int alg_arg, int alg2_arg, int type_arg, data_t *key_data, int invalidate_method_arg) { psa_key_lifetime_t lifetime = lifetime_arg; mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make(owner_id_arg, id_arg); psa_algorithm_t alg = alg_arg; psa_algorithm_t alg2 = alg2_arg; psa_key_usage_t usage_flags = usage_arg; psa_key_type_t type = type_arg; invalidate_method_t invalidate_method = invalidate_method_arg; mbedtls_svc_key_id_t returned_id = MBEDTLS_SVC_KEY_ID_INIT; psa_key_handle_t handle = PSA_KEY_HANDLE_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_key_attributes_t read_attributes = PSA_KEY_ATTRIBUTES_INIT; uint8_t *reexported = NULL; size_t reexported_length = -1; #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) mbedtls_svc_key_id_t wrong_owner_id = mbedtls_svc_key_id_make(owner_id_arg + 1, id_arg); mbedtls_svc_key_id_t invalid_svc_key_id = MBEDTLS_SVC_KEY_ID_INIT; #endif TEST_USES_KEY_ID(id); mbedtls_test_set_step(1); 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_usage_flags(&attributes, usage_flags); psa_set_key_algorithm(&attributes, alg); psa_set_key_enrollment_algorithm(&attributes, alg2); PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len, &returned_id)); TEST_ASSERT(mbedtls_svc_key_id_equal(id, returned_id)); #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) TEST_EQUAL(psa_open_key(wrong_owner_id, &invalid_svc_key_id), PSA_ERROR_DOES_NOT_EXIST); #endif PSA_ASSERT(psa_get_key_attributes(id, &attributes)); TEST_EQUAL(psa_get_key_lifetime(&attributes), lifetime); TEST_ASSERT(mbedtls_svc_key_id_equal( psa_get_key_id(&attributes), id)); TEST_EQUAL(psa_get_key_usage_flags(&attributes), mbedtls_test_update_key_usage_flags(usage_flags)); TEST_EQUAL(psa_get_key_algorithm(&attributes), alg); TEST_EQUAL(psa_get_key_enrollment_algorithm(&attributes), alg2); TEST_EQUAL(psa_get_key_type(&attributes), type); /* Close the key and then open it. */ PSA_ASSERT(psa_close_key(id)); #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) TEST_EQUAL(psa_open_key(wrong_owner_id, &invalid_svc_key_id), PSA_ERROR_DOES_NOT_EXIST); #endif PSA_ASSERT(psa_open_key(id, &handle)); TEST_ASSERT(!psa_key_handle_is_null(handle)); PSA_ASSERT(psa_get_key_attributes(handle, &attributes)); TEST_EQUAL(psa_get_key_lifetime(&attributes), lifetime); TEST_ASSERT(mbedtls_svc_key_id_equal( psa_get_key_id(&attributes), id)); TEST_EQUAL(psa_get_key_usage_flags(&attributes), mbedtls_test_update_key_usage_flags(usage_flags)); TEST_EQUAL(psa_get_key_algorithm(&attributes), alg); TEST_EQUAL(psa_get_key_enrollment_algorithm(&attributes), alg2); TEST_EQUAL(psa_get_key_type(&attributes), type); /* * Do something that wipes key data in volatile memory or destroy the * key. */ mbedtls_test_set_step(2); if (!invalidate_key(invalidate_method, id)) { goto exit; } if (!invalidate_psa(invalidate_method)) { goto exit; } /* Try to reaccess the key. If we destroyed it, check that it doesn't * exist. Otherwise check that it still exists and has the expected * content. */ switch (invalidate_method) { case INVALIDATE_BY_CLOSING: case INVALIDATE_BY_CLOSING_WITH_SHUTDOWN: case INVALIDATE_BY_PURGING: case INVALIDATE_BY_PURGING_WITH_SHUTDOWN: case INVALIDATE_BY_SHUTDOWN: PSA_ASSERT(psa_open_key(id, &handle)); PSA_ASSERT(psa_get_key_attributes(id, &read_attributes)); TEST_EQUAL(psa_get_key_lifetime(&attributes), psa_get_key_lifetime(&read_attributes)); TEST_ASSERT(mbedtls_svc_key_id_equal( psa_get_key_id(&attributes), psa_get_key_id(&read_attributes))); TEST_EQUAL(psa_get_key_usage_flags(&attributes), mbedtls_test_update_key_usage_flags(usage_flags)); TEST_EQUAL(psa_get_key_algorithm(&attributes), psa_get_key_algorithm(&read_attributes)); TEST_EQUAL(psa_get_key_enrollment_algorithm(&attributes), psa_get_key_enrollment_algorithm(&read_attributes)); TEST_EQUAL(psa_get_key_type(&attributes), psa_get_key_type(&read_attributes)); TEST_EQUAL(psa_get_key_bits(&attributes), psa_get_key_bits(&read_attributes)); TEST_CALLOC(reexported, key_data->len); if (usage_flags & PSA_KEY_USAGE_EXPORT) { PSA_ASSERT(psa_export_key(id, reexported, key_data->len, &reexported_length)); TEST_MEMORY_COMPARE(key_data->x, key_data->len, reexported, reexported_length); } else { TEST_EQUAL(psa_export_key(id, reexported, key_data->len, &reexported_length), PSA_ERROR_NOT_PERMITTED); } PSA_ASSERT(psa_close_key(handle)); break; case INVALIDATE_BY_DESTROYING: case INVALIDATE_BY_DESTROYING_WITH_SHUTDOWN: /* * Test that the key handle and identifier are now not referring to an * existing key. */ TEST_EQUAL(psa_get_key_attributes(handle, &read_attributes), PSA_ERROR_INVALID_HANDLE); TEST_EQUAL(psa_close_key(handle), PSA_ERROR_INVALID_HANDLE); TEST_EQUAL(psa_get_key_attributes(id, &read_attributes), PSA_ERROR_INVALID_HANDLE); break; } exit: /* * Key attributes may have been returned by psa_get_key_attributes() * thus reset them as required. */ psa_reset_key_attributes(&attributes); psa_reset_key_attributes(&read_attributes); PSA_DONE(); mbedtls_free(reexported); } /* END_CASE */ /* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C */ void create_existent(int lifetime_arg, int owner_id_arg, int id_arg, int reopen_policy_arg) { psa_key_lifetime_t lifetime = lifetime_arg; mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make(owner_id_arg, id_arg); mbedtls_svc_key_id_t returned_id = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_key_type_t type1 = PSA_KEY_TYPE_RAW_DATA; const uint8_t material1[5] = "a key"; const uint8_t material2[5] = "b key"; size_t bits1 = PSA_BYTES_TO_BITS(sizeof(material1)); uint8_t reexported[sizeof(material1)]; size_t reexported_length; reopen_policy_t reopen_policy = reopen_policy_arg; TEST_USES_KEY_ID(id); PSA_ASSERT(psa_crypto_init()); /* Create a key. */ psa_set_key_id(&attributes, id); psa_set_key_lifetime(&attributes, lifetime); psa_set_key_type(&attributes, type1); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT); psa_set_key_algorithm(&attributes, 0); PSA_ASSERT(psa_import_key(&attributes, material1, sizeof(material1), &returned_id)); TEST_ASSERT(mbedtls_svc_key_id_equal(id, returned_id)); if (reopen_policy == CLOSE_BEFORE) { PSA_ASSERT(psa_close_key(id)); } /* Attempt to create a new key in the same slot. */ TEST_EQUAL(psa_import_key(&attributes, material2, sizeof(material2), &returned_id), PSA_ERROR_ALREADY_EXISTS); TEST_ASSERT(mbedtls_svc_key_id_is_null(returned_id)); if (reopen_policy == CLOSE_AFTER) { PSA_ASSERT(psa_close_key(id)); } /* Check that the original key hasn't changed. */ psa_reset_key_attributes(&attributes); PSA_ASSERT(psa_get_key_attributes(id, &attributes)); TEST_ASSERT(mbedtls_svc_key_id_equal( psa_get_key_id(&attributes), id)); TEST_EQUAL(psa_get_key_lifetime(&attributes), lifetime); TEST_EQUAL(psa_get_key_type(&attributes), type1); TEST_EQUAL(psa_get_key_bits(&attributes), bits1); TEST_EQUAL(psa_get_key_usage_flags(&attributes), PSA_KEY_USAGE_EXPORT); TEST_EQUAL(psa_get_key_algorithm(&attributes), 0); PSA_ASSERT(psa_export_key(id, reexported, sizeof(reexported), &reexported_length)); TEST_MEMORY_COMPARE(material1, sizeof(material1), reexported, reexported_length); PSA_ASSERT(psa_close_key(id)); exit: /* * Key attributes may have been returned by psa_get_key_attributes() * thus reset them as required. */ psa_reset_key_attributes(&attributes); PSA_DONE(); } /* END_CASE */ /* BEGIN_CASE */ void open_fail(int id_arg, int expected_status_arg) { mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make(1, id_arg); psa_status_t expected_status = expected_status_arg; psa_key_handle_t handle = mbedtls_svc_key_id_make(0xdead, 0xdead); PSA_ASSERT(psa_crypto_init()); TEST_EQUAL(psa_open_key(id, &handle), expected_status); TEST_ASSERT(psa_key_handle_is_null(handle)); exit: PSA_DONE(); } /* END_CASE */ /* BEGIN_CASE */ void create_fail(int lifetime_arg, int id_arg, int expected_status_arg) { psa_key_lifetime_t lifetime = lifetime_arg; mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make(1, id_arg); psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_status_t expected_status = expected_status_arg; mbedtls_svc_key_id_t returned_id = mbedtls_svc_key_id_make(0xdead, 0xdead); uint8_t material[1] = { 'k' }; TEST_USES_KEY_ID(id); PSA_ASSERT(psa_crypto_init()); psa_set_key_lifetime(&attributes, lifetime); if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) { /* * Not possible to set a key identifier different from 0 through * PSA key attributes APIs thus accessing to the attributes * directly. */ attributes.id = id; } else { psa_set_key_id(&attributes, id); } psa_set_key_type(&attributes, PSA_KEY_TYPE_RAW_DATA); TEST_EQUAL(psa_import_key(&attributes, material, sizeof(material), &returned_id), expected_status); TEST_ASSERT(mbedtls_svc_key_id_is_null(returned_id)); exit: PSA_DONE(); } /* END_CASE */ /* BEGIN_CASE */ void copy_across_lifetimes(int source_lifetime_arg, int source_owner_id_arg, int source_id_arg, int source_usage_arg, int source_alg_arg, int source_alg2_arg, int type_arg, data_t *material, int target_lifetime_arg, int target_owner_id_arg, int target_id_arg, int target_usage_arg, int target_alg_arg, int target_alg2_arg, int expected_usage_arg, int expected_alg_arg, int expected_alg2_arg) { psa_key_lifetime_t source_lifetime = source_lifetime_arg; mbedtls_svc_key_id_t source_id = mbedtls_svc_key_id_make(source_owner_id_arg, source_id_arg); psa_key_usage_t source_usage = source_usage_arg; psa_algorithm_t source_alg = source_alg_arg; psa_key_attributes_t source_attributes = PSA_KEY_ATTRIBUTES_INIT; psa_key_type_t source_type = type_arg; mbedtls_svc_key_id_t returned_source_id = MBEDTLS_SVC_KEY_ID_INIT; psa_key_lifetime_t target_lifetime = target_lifetime_arg; mbedtls_svc_key_id_t target_id = mbedtls_svc_key_id_make(target_owner_id_arg, target_id_arg); psa_key_usage_t target_usage = target_usage_arg; psa_algorithm_t target_alg = target_alg_arg; psa_key_attributes_t target_attributes = PSA_KEY_ATTRIBUTES_INIT; mbedtls_svc_key_id_t returned_target_id = MBEDTLS_SVC_KEY_ID_INIT; psa_key_handle_t target_handle = PSA_KEY_HANDLE_INIT; psa_key_usage_t expected_usage = expected_usage_arg; psa_algorithm_t expected_alg = expected_alg_arg; psa_algorithm_t expected_alg2 = expected_alg2_arg; uint8_t *export_buffer = NULL; TEST_USES_KEY_ID(source_id); TEST_USES_KEY_ID(target_id); PSA_ASSERT(psa_crypto_init()); /* Populate the source slot. */ psa_set_key_id(&source_attributes, source_id); psa_set_key_lifetime(&source_attributes, source_lifetime); psa_set_key_type(&source_attributes, source_type); psa_set_key_usage_flags(&source_attributes, source_usage); psa_set_key_algorithm(&source_attributes, source_alg); psa_set_key_enrollment_algorithm(&source_attributes, source_alg2_arg); PSA_ASSERT(psa_import_key(&source_attributes, material->x, material->len, &returned_source_id)); /* Update the attributes with the bit size. */ PSA_ASSERT(psa_get_key_attributes(returned_source_id, &source_attributes)); /* Prepare the target slot. */ psa_set_key_id(&target_attributes, target_id); psa_set_key_lifetime(&target_attributes, target_lifetime); psa_set_key_usage_flags(&target_attributes, target_usage); psa_set_key_algorithm(&target_attributes, target_alg); psa_set_key_enrollment_algorithm(&target_attributes, target_alg2_arg); /* Copy the key. */ PSA_ASSERT(psa_copy_key(returned_source_id, &target_attributes, &returned_target_id)); /* Destroy the source to ensure that this doesn't affect the target. */ PSA_ASSERT(psa_destroy_key(returned_source_id)); /* If the target key is persistent, restart the system to make * sure that the material is still alive. */ if (!PSA_KEY_LIFETIME_IS_VOLATILE(target_lifetime)) { mbedtls_psa_crypto_free(); PSA_ASSERT(psa_crypto_init()); PSA_ASSERT(psa_open_key(target_id, &target_handle)); } /* Test that the target slot has the expected content. */ psa_reset_key_attributes(&target_attributes); PSA_ASSERT(psa_get_key_attributes(returned_target_id, &target_attributes)); if (!PSA_KEY_LIFETIME_IS_VOLATILE(target_lifetime)) { TEST_ASSERT(mbedtls_svc_key_id_equal( target_id, psa_get_key_id(&target_attributes))); } else { #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) TEST_EQUAL(MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(returned_target_id), target_owner_id_arg); #endif } TEST_EQUAL(target_lifetime, psa_get_key_lifetime(&target_attributes)); TEST_EQUAL(source_type, psa_get_key_type(&target_attributes)); TEST_EQUAL(psa_get_key_bits(&source_attributes), psa_get_key_bits(&target_attributes)); TEST_EQUAL(expected_usage, psa_get_key_usage_flags(&target_attributes)); TEST_EQUAL(expected_alg, psa_get_key_algorithm(&target_attributes)); TEST_EQUAL(expected_alg2, psa_get_key_enrollment_algorithm(&target_attributes)); if (expected_usage & PSA_KEY_USAGE_EXPORT) { size_t length; TEST_CALLOC(export_buffer, material->len); PSA_ASSERT(psa_export_key(returned_target_id, export_buffer, material->len, &length)); TEST_MEMORY_COMPARE(material->x, material->len, export_buffer, length); } else { size_t length; /* Check that the key is actually non-exportable. */ TEST_EQUAL(psa_export_key(returned_target_id, export_buffer, material->len, &length), PSA_ERROR_NOT_PERMITTED); } PSA_ASSERT(psa_destroy_key(returned_target_id)); exit: /* * Source and target key attributes may have been returned by * psa_get_key_attributes() thus reset them as required. */ psa_reset_key_attributes(&source_attributes); psa_reset_key_attributes(&target_attributes); PSA_DONE(); mbedtls_free(export_buffer); } /* END_CASE */ /* BEGIN_CASE */ void copy_to_occupied(int source_lifetime_arg, int source_id_arg, int source_usage_arg, int source_alg_arg, int source_type_arg, data_t *source_material, int target_lifetime_arg, int target_id_arg, int target_usage_arg, int target_alg_arg, int target_type_arg, data_t *target_material) { psa_key_lifetime_t source_lifetime = source_lifetime_arg; mbedtls_svc_key_id_t source_id = mbedtls_svc_key_id_make(1, source_id_arg); psa_key_usage_t source_usage = source_usage_arg; psa_algorithm_t source_alg = source_alg_arg; psa_key_type_t source_type = source_type_arg; mbedtls_svc_key_id_t returned_source_id = MBEDTLS_SVC_KEY_ID_INIT; psa_key_lifetime_t target_lifetime = target_lifetime_arg; mbedtls_svc_key_id_t target_id = mbedtls_svc_key_id_make(1, target_id_arg); psa_key_usage_t target_usage = target_usage_arg; psa_algorithm_t target_alg = target_alg_arg; psa_key_type_t target_type = target_type_arg; mbedtls_svc_key_id_t returned_target_id = MBEDTLS_SVC_KEY_ID_INIT; mbedtls_svc_key_id_t new_key = MBEDTLS_SVC_KEY_ID_INIT; uint8_t *export_buffer = NULL; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_key_attributes_t attributes1 = PSA_KEY_ATTRIBUTES_INIT; psa_key_attributes_t attributes2 = PSA_KEY_ATTRIBUTES_INIT; TEST_USES_KEY_ID(source_id); TEST_USES_KEY_ID(target_id); PSA_ASSERT(psa_crypto_init()); /* Populate the source slot. */ if (!PSA_KEY_LIFETIME_IS_VOLATILE(source_lifetime)) { psa_set_key_id(&attributes, source_id); psa_set_key_lifetime(&attributes, source_lifetime); } psa_set_key_type(&attributes, source_type); psa_set_key_usage_flags(&attributes, source_usage); psa_set_key_algorithm(&attributes, source_alg); PSA_ASSERT(psa_import_key(&attributes, source_material->x, source_material->len, &returned_source_id)); /* Populate the target slot. */ if (mbedtls_svc_key_id_equal(target_id, source_id)) { returned_target_id = returned_source_id; } else { psa_set_key_id(&attributes1, target_id); psa_set_key_lifetime(&attributes1, target_lifetime); psa_set_key_type(&attributes1, target_type); psa_set_key_usage_flags(&attributes1, target_usage); psa_set_key_algorithm(&attributes1, target_alg); PSA_ASSERT(psa_import_key(&attributes1, target_material->x, target_material->len, &returned_target_id)); } PSA_ASSERT(psa_get_key_attributes(returned_target_id, &attributes1)); /* Make a copy attempt. */ psa_set_key_id(&attributes, target_id); psa_set_key_lifetime(&attributes, target_lifetime); TEST_EQUAL(psa_copy_key(returned_source_id, &attributes, &new_key), PSA_ERROR_ALREADY_EXISTS); TEST_ASSERT(mbedtls_svc_key_id_is_null(new_key)); /* Test that the target slot is unaffected. */ PSA_ASSERT(psa_get_key_attributes(returned_target_id, &attributes2)); TEST_ASSERT(mbedtls_svc_key_id_equal( psa_get_key_id(&attributes1), psa_get_key_id(&attributes2))); TEST_EQUAL(psa_get_key_lifetime(&attributes1), psa_get_key_lifetime(&attributes2)); TEST_EQUAL(psa_get_key_type(&attributes1), psa_get_key_type(&attributes2)); TEST_EQUAL(psa_get_key_bits(&attributes1), psa_get_key_bits(&attributes2)); TEST_EQUAL(psa_get_key_usage_flags(&attributes1), psa_get_key_usage_flags(&attributes2)); TEST_EQUAL(psa_get_key_algorithm(&attributes1), psa_get_key_algorithm(&attributes2)); if (target_usage & PSA_KEY_USAGE_EXPORT) { size_t length; TEST_CALLOC(export_buffer, target_material->len); PSA_ASSERT(psa_export_key(returned_target_id, export_buffer, target_material->len, &length)); TEST_MEMORY_COMPARE(target_material->x, target_material->len, export_buffer, length); } PSA_ASSERT(psa_destroy_key(returned_source_id)); if (!mbedtls_svc_key_id_equal(target_id, source_id)) { PSA_ASSERT(psa_destroy_key(returned_target_id)); } exit: /* * Key attributes may have been returned by psa_get_key_attributes() * thus reset them as required. */ psa_reset_key_attributes(&attributes1); psa_reset_key_attributes(&attributes2); PSA_DONE(); mbedtls_free(export_buffer); } /* END_CASE */ /* BEGIN_CASE */ void invalid_handle(int handle_construction, int close_status_arg) { psa_key_handle_t valid_handle = PSA_KEY_HANDLE_INIT; psa_key_handle_t invalid_handle = PSA_KEY_HANDLE_INIT; psa_key_id_t key_id; psa_status_t close_status = close_status_arg; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; uint8_t material[1] = "a"; PSA_ASSERT(psa_crypto_init()); /* Allocate a handle and store a key in it. */ psa_set_key_type(&attributes, PSA_KEY_TYPE_RAW_DATA); psa_set_key_usage_flags(&attributes, 0); psa_set_key_algorithm(&attributes, 0); PSA_ASSERT(psa_import_key(&attributes, material, sizeof(material), &valid_handle)); TEST_ASSERT(!psa_key_handle_is_null(valid_handle)); /* Construct an invalid handle as specified in the test case data. */ switch (handle_construction) { case INVALID_HANDLE_0: invalid_handle = PSA_KEY_HANDLE_INIT; break; case INVALID_HANDLE_UNOPENED: /* * MBEDTLS_SVC_KEY_ID_GET_KEY_ID( valid_handle ) is a volatile * key identifier as the imported key is a volatile key. Volatile * key identifiers are in the range from PSA_KEY_ID_VOLATILE_MIN * to PSA_KEY_ID_VOLATILE_MAX included. It is very unlikely that * all IDs are used up to the last one, so pick * PSA_KEY_ID_VOLATILE_MAX to build an unopened and thus invalid * identifier. */ key_id = PSA_KEY_ID_VOLATILE_MAX; invalid_handle = mbedtls_svc_key_id_make(0, key_id); break; case INVALID_HANDLE_CLOSED: PSA_ASSERT(psa_import_key(&attributes, material, sizeof(material), &invalid_handle)); PSA_ASSERT(psa_destroy_key(invalid_handle)); break; case INVALID_HANDLE_HUGE: invalid_handle = mbedtls_svc_key_id_make(0, PSA_KEY_ID_VENDOR_MAX + 1); break; default: TEST_FAIL("unknown handle construction"); } /* Attempt to use the invalid handle. */ TEST_EQUAL(psa_get_key_attributes(invalid_handle, &attributes), PSA_ERROR_INVALID_HANDLE); TEST_EQUAL(psa_close_key(invalid_handle), close_status); TEST_EQUAL(psa_destroy_key(invalid_handle), close_status); /* After all this, check that the original handle is intact. */ PSA_ASSERT(psa_get_key_attributes(valid_handle, &attributes)); TEST_EQUAL(psa_get_key_type(&attributes), PSA_KEY_TYPE_RAW_DATA); TEST_EQUAL(psa_get_key_bits(&attributes), PSA_BYTES_TO_BITS(sizeof(material))); PSA_ASSERT(psa_close_key(valid_handle)); exit: /* * Key attributes may have been returned by psa_get_key_attributes() * thus reset them as required. */ psa_reset_key_attributes(&attributes); PSA_DONE(); } /* END_CASE */ /* BEGIN_CASE */ void many_transient_keys(int max_keys_arg) { mbedtls_svc_key_id_t *keys = NULL; size_t max_keys = max_keys_arg; size_t i, j; psa_status_t status; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; uint8_t exported[sizeof(size_t)]; size_t exported_length; TEST_CALLOC(keys, max_keys); PSA_ASSERT(psa_crypto_init()); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT); psa_set_key_algorithm(&attributes, 0); psa_set_key_type(&attributes, PSA_KEY_TYPE_RAW_DATA); for (i = 0; i < max_keys; i++) { status = psa_import_key(&attributes, (uint8_t *) &i, sizeof(i), &keys[i]); if (status == PSA_ERROR_INSUFFICIENT_MEMORY) { break; } PSA_ASSERT(status); TEST_ASSERT(!mbedtls_svc_key_id_is_null(keys[i])); for (j = 0; j < i; j++) { TEST_ASSERT(!mbedtls_svc_key_id_equal(keys[i], keys[j])); } } max_keys = i; for (i = 1; i < max_keys; i++) { PSA_ASSERT(psa_close_key(keys[i - 1])); PSA_ASSERT(psa_export_key(keys[i], exported, sizeof(exported), &exported_length)); TEST_MEMORY_COMPARE(exported, exported_length, (uint8_t *) &i, sizeof(i)); } PSA_ASSERT(psa_close_key(keys[i - 1])); exit: PSA_DONE(); mbedtls_free(keys); } /* END_CASE */ /* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C */ void key_slot_eviction_to_import_new_key(int lifetime_arg) { psa_key_lifetime_t lifetime = (psa_key_lifetime_t) lifetime_arg; size_t i; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; uint8_t exported[sizeof(size_t)]; size_t exported_length; mbedtls_svc_key_id_t key, returned_key_id; PSA_ASSERT(psa_crypto_init()); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT); psa_set_key_algorithm(&attributes, 0); psa_set_key_type(&attributes, PSA_KEY_TYPE_RAW_DATA); /* * Create MBEDTLS_PSA_KEY_SLOT_COUNT persistent keys. */ for (i = 0; i < MBEDTLS_PSA_KEY_SLOT_COUNT; i++) { key = mbedtls_svc_key_id_make(i, i + 1); psa_set_key_id(&attributes, key); PSA_ASSERT(psa_import_key(&attributes, (uint8_t *) &i, sizeof(i), &returned_key_id)); TEST_ASSERT(mbedtls_svc_key_id_equal(returned_key_id, key)); } /* * Create a new persistent or volatile key. When creating the key, * one of the descriptions of the previously created persistent keys * is removed from the RAM key slots. This makes room to store its * description in RAM. */ i = MBEDTLS_PSA_KEY_SLOT_COUNT; key = mbedtls_svc_key_id_make(i, i + 1); psa_set_key_id(&attributes, key); psa_set_key_lifetime(&attributes, lifetime); PSA_ASSERT(psa_import_key(&attributes, (uint8_t *) &i, sizeof(i), &returned_key_id)); if (lifetime != PSA_KEY_LIFETIME_VOLATILE) { TEST_ASSERT(mbedtls_svc_key_id_equal(returned_key_id, key)); } else { TEST_ASSERT(psa_key_id_is_volatile( MBEDTLS_SVC_KEY_ID_GET_KEY_ID(returned_key_id))); } /* * Check that we can export all ( MBEDTLS_PSA_KEY_SLOT_COUNT + 1 ) keys, * that they have the expected value and destroy them. In that process, * the description of the persistent key that was evicted from the RAM * slots when creating the last key is restored in a RAM slot to export * its value. */ for (i = 0; i <= MBEDTLS_PSA_KEY_SLOT_COUNT; i++) { if (i < MBEDTLS_PSA_KEY_SLOT_COUNT) { key = mbedtls_svc_key_id_make(i, i + 1); } else { key = returned_key_id; } PSA_ASSERT(psa_export_key(key, exported, sizeof(exported), &exported_length)); TEST_MEMORY_COMPARE(exported, exported_length, (uint8_t *) &i, sizeof(i)); PSA_ASSERT(psa_destroy_key(key)); } exit: PSA_DONE(); } /* END_CASE */ /* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C */ void non_reusable_key_slots_integrity_in_case_of_key_slot_starvation() { psa_status_t status; size_t i; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; uint8_t exported[sizeof(size_t)]; size_t exported_length; mbedtls_svc_key_id_t persistent_key = MBEDTLS_SVC_KEY_ID_INIT; mbedtls_svc_key_id_t persistent_key2 = MBEDTLS_SVC_KEY_ID_INIT; mbedtls_svc_key_id_t returned_key_id = MBEDTLS_SVC_KEY_ID_INIT; mbedtls_svc_key_id_t *keys = NULL; mbedtls_psa_stats_t psa_key_slots_stats; size_t available_key_slots = 0; TEST_ASSERT(MBEDTLS_PSA_KEY_SLOT_COUNT >= 1); PSA_ASSERT(psa_crypto_init()); mbedtls_psa_get_stats(&psa_key_slots_stats); available_key_slots = psa_key_slots_stats.empty_slots; TEST_CALLOC(keys, available_key_slots); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY); psa_set_key_algorithm(&attributes, 0); psa_set_key_type(&attributes, PSA_KEY_TYPE_RAW_DATA); /* * Create a persistent key */ persistent_key = mbedtls_svc_key_id_make(0x100, 0x205); psa_set_key_id(&attributes, persistent_key); PSA_ASSERT(psa_import_key(&attributes, (uint8_t *) &persistent_key, sizeof(persistent_key), &returned_key_id)); TEST_ASSERT(mbedtls_svc_key_id_equal(returned_key_id, persistent_key)); /* * Create the maximum available number of volatile keys */ psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE); for (i = 0; i < available_key_slots; i++) { PSA_ASSERT(psa_import_key(&attributes, (uint8_t *) &i, sizeof(i), &keys[i])); } psa_reset_key_attributes(&attributes); /* * Check that we cannot access the persistent key as all slots are * occupied by volatile keys and the implementation needs to load the * persistent key description in a slot to be able to access it. */ status = psa_get_key_attributes(persistent_key, &attributes); TEST_EQUAL(status, PSA_ERROR_INSUFFICIENT_MEMORY); /* * Check we can export the volatile key created last and that it has the * expected value. Then, destroy it. */ PSA_ASSERT(psa_export_key(keys[available_key_slots - 1], exported, sizeof(exported), &exported_length)); i = available_key_slots - 1; TEST_MEMORY_COMPARE(exported, exported_length, (uint8_t *) &i, sizeof(i)); PSA_ASSERT(psa_destroy_key(keys[available_key_slots - 1])); /* * Check that we can now access the persistent key again. */ PSA_ASSERT(psa_get_key_attributes(persistent_key, &attributes)); TEST_ASSERT(mbedtls_svc_key_id_equal(attributes.id, persistent_key)); /* * Check that we cannot copy the persistent key as all slots are occupied * by the persistent key and the volatile keys and the slot containing the * persistent key cannot be reclaimed as it contains the key to copy. */ persistent_key2 = mbedtls_svc_key_id_make(0x100, 0x204); psa_set_key_id(&attributes, persistent_key2); status = psa_copy_key(persistent_key, &attributes, &returned_key_id); TEST_EQUAL(status, PSA_ERROR_INSUFFICIENT_MEMORY); /* * Check we can export the remaining volatile keys and that they have the * expected values. */ for (i = 0; i < (available_key_slots - 1); i++) { PSA_ASSERT(psa_export_key(keys[i], exported, sizeof(exported), &exported_length)); TEST_MEMORY_COMPARE(exported, exported_length, (uint8_t *) &i, sizeof(i)); PSA_ASSERT(psa_destroy_key(keys[i])); } /* * Check we can export the persistent key and that it have the expected * value. */ PSA_ASSERT(psa_export_key(persistent_key, exported, sizeof(exported), &exported_length)); TEST_MEMORY_COMPARE(exported, exported_length, (uint8_t *) &persistent_key, sizeof(persistent_key)); exit: /* * Key attributes may have been returned by psa_get_key_attributes() * thus reset them as required. */ psa_reset_key_attributes(&attributes); psa_destroy_key(persistent_key); PSA_DONE(); mbedtls_free(keys); } /* END_CASE */