From 5d4b9cb2e2d521d218ff0b6bf7cece1e18ec902c Mon Sep 17 00:00:00 2001 From: Tom Cosgrove Date: Fri, 21 Jun 2024 16:13:01 +0100 Subject: [PATCH] psasim: add support for psa_generate_key*() to the simulator Signed-off-by: Tom Cosgrove --- .../psasim/src/psa_functions_codes.h | 2 + .../psasim/src/psa_sim_crypto_client.c | 144 +++++++++++++++ .../psasim/src/psa_sim_crypto_server.c | 172 ++++++++++++++++++ .../psasim/src/psa_sim_generate.pl | 105 +++++++++++ 4 files changed, 423 insertions(+) diff --git a/tests/psa-client-server/psasim/src/psa_functions_codes.h b/tests/psa-client-server/psasim/src/psa_functions_codes.h index c9b72e6f68..39142c5e58 100644 --- a/tests/psa-client-server/psasim/src/psa_functions_codes.h +++ b/tests/psa-client-server/psasim/src/psa_functions_codes.h @@ -34,6 +34,8 @@ enum { PSA_CIPHER_SET_IV, PSA_CIPHER_UPDATE, PSA_DESTROY_KEY, + PSA_GENERATE_KEY, + PSA_GENERATE_KEY_EXT, PSA_GENERATE_RANDOM, PSA_GET_KEY_ATTRIBUTES, PSA_HASH_ABORT, diff --git a/tests/psa-client-server/psasim/src/psa_sim_crypto_client.c b/tests/psa-client-server/psasim/src/psa_sim_crypto_client.c index 84f2b5a6ab..5b84f2d84b 100644 --- a/tests/psa-client-server/psasim/src/psa_sim_crypto_client.c +++ b/tests/psa-client-server/psasim/src/psa_sim_crypto_client.c @@ -1918,6 +1918,150 @@ fail: } +psa_status_t psa_generate_key( + const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *key + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = psasim_serialise_begin_needs() + + psasim_serialise_psa_key_attributes_t_needs(*attributes) + + psasim_serialise_mbedtls_svc_key_id_t_needs(*key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_attributes_t(&pos, &remaining, *attributes); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, *key); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_GENERATE_KEY, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_GENERATE_KEY server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t(&rpos, &rremain, key); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_generate_key_ext( + const psa_key_attributes_t *attributes, + const psa_key_production_parameters_t *params, size_t params_data_length, + mbedtls_svc_key_id_t *key + ) +{ + uint8_t *ser_params = NULL; + uint8_t *ser_result = NULL; + size_t result_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t needed = psasim_serialise_begin_needs() + + psasim_serialise_psa_key_attributes_t_needs(*attributes) + + psasim_serialise_psa_key_production_parameters_t_needs(params, params_data_length) + + psasim_serialise_mbedtls_svc_key_id_t_needs(*key); + + ser_params = malloc(needed); + if (ser_params == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto fail; + } + + uint8_t *pos = ser_params; + size_t remaining = needed; + int ok; + ok = psasim_serialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_attributes_t(&pos, &remaining, *attributes); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_key_production_parameters_t(&pos, &remaining, params, params_data_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_mbedtls_svc_key_id_t(&pos, &remaining, *key); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_GENERATE_KEY_EXT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_GENERATE_KEY_EXT server call failed\n"); + goto fail; + } + + uint8_t *rpos = ser_result; + size_t rremain = result_length; + + ok = psasim_deserialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t(&rpos, &rremain, key); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + psa_status_t psa_generate_random( uint8_t *output, size_t output_size ) diff --git a/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c b/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c index 92ce96a904..5d6b608a90 100644 --- a/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c +++ b/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c @@ -2172,6 +2172,170 @@ fail: return 0; // This shouldn't happen! } +// Returns 1 for success, 0 for failure +int psa_generate_key_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes; + mbedtls_svc_key_id_t key; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_attributes_t(&pos, &remaining, &attributes); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_generate_key( + &attributes, + &key + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_mbedtls_svc_key_id_t(&rpos, &rremain, key); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + return 1; // success + +fail: + free(result); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_generate_key_ext_wrapper( + uint8_t *in_params, size_t in_params_len, + uint8_t **out_params, size_t *out_params_len) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes; + psa_key_production_parameters_t *params = NULL; + size_t params_data_length; + mbedtls_svc_key_id_t key; + + uint8_t *pos = in_params; + size_t remaining = in_params_len; + uint8_t *result = NULL; + int ok; + + ok = psasim_deserialise_begin(&pos, &remaining); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_attributes_t(&pos, &remaining, &attributes); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_key_production_parameters_t(&pos, &remaining, ¶ms, ¶ms_data_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_mbedtls_svc_key_id_t(&pos, &remaining, &key); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_generate_key_ext( + &attributes, + params, params_data_length, + &key + ); + + // NOTE: Should really check there is no overflow as we go along. + size_t result_size = + psasim_serialise_begin_needs() + + psasim_serialise_psa_status_t_needs(status) + + psasim_serialise_mbedtls_svc_key_id_t_needs(key); + + result = malloc(result_size); + if (result == NULL) { + goto fail; + } + + uint8_t *rpos = result; + size_t rremain = result_size; + + ok = psasim_serialise_begin(&rpos, &rremain); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_psa_status_t(&rpos, &rremain, status); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_mbedtls_svc_key_id_t(&rpos, &rremain, key); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(params); + + return 1; // success + +fail: + free(result); + + free(params); + + return 0; // This shouldn't happen! +} + // Returns 1 for success, 0 for failure int psa_generate_random_wrapper( uint8_t *in_params, size_t in_params_len, @@ -4944,6 +5108,14 @@ psa_status_t psa_crypto_call(psa_msg_t msg) ok = psa_destroy_key_wrapper(in_params, in_params_len, &out_params, &out_params_len); break; + case PSA_GENERATE_KEY: + ok = psa_generate_key_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_GENERATE_KEY_EXT: + ok = psa_generate_key_ext_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; case PSA_GENERATE_RANDOM: ok = psa_generate_random_wrapper(in_params, in_params_len, &out_params, &out_params_len); diff --git a/tests/psa-client-server/psasim/src/psa_sim_generate.pl b/tests/psa-client-server/psasim/src/psa_sim_generate.pl index 5510be1fe5..42f7ac7bd1 100755 --- a/tests/psa-client-server/psasim/src/psa_sim_generate.pl +++ b/tests/psa-client-server/psasim/src/psa_sim_generate.pl @@ -4198,3 +4198,108 @@ psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, uint8_t *output, size_t output_size, size_t *output_length); + +/** + * \brief Generate a key or key pair. + * + * The key is generated randomly. + * Its location, usage policy, type and size are taken from \p attributes. + * + * Implementations must reject an attempt to generate a key of size 0. + * + * The following type-specific considerations apply: + * - For RSA keys (#PSA_KEY_TYPE_RSA_KEY_PAIR), + * the public exponent is 65537. + * The modulus is a product of two probabilistic primes + * between 2^{n-1} and 2^n where n is the bit size specified in the + * attributes. + * + * \note This function is equivalent to calling psa_generate_key_ext() + * with the production parameters #PSA_KEY_PRODUCTION_PARAMETERS_INIT + * and `params_data_length == 0` (i.e. `params->data` is empty). + * + * \param[in] attributes The attributes for the new key. + * \param[out] key On success, an identifier for the newly created + * key. For persistent keys, this is the key + * identifier defined in \p attributes. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *key); + +/** + * \brief Generate a key or key pair using custom production parameters. + * + * See the description of psa_generate_key() for the operation of this + * function with the default production parameters. In addition, this function + * supports the following production customizations, described in more detail + * in the documentation of ::psa_key_production_parameters_t: + * + * - RSA keys: generation with a custom public exponent. + * + * \note This function is experimental and may change in future minor + * versions of Mbed TLS. + * + * \param[in] attributes The attributes for the new key. + * \param[in] params Customization parameters for the key generation. + * When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT + * with \p params_data_length = 0, + * this function is equivalent to + * psa_generate_key(). + * \param params_data_length + * Length of `params->data` in bytes. + * \param[out] key On success, an identifier for the newly created + * key. For persistent keys, this is the key + * identifier defined in \p attributes. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_generate_key_ext(const psa_key_attributes_t *attributes, + const psa_key_production_parameters_t *params, + size_t params_data_length, + mbedtls_svc_key_id_t *key);