From 8f1c913e38f82f0d56c658495868f385669d64cd Mon Sep 17 00:00:00 2001 From: Tom Cosgrove Date: Fri, 21 Jun 2024 16:17:30 +0100 Subject: [PATCH] psasim: add support for psa_asymmetric_{encrypt,decrypt}() to the simulator Signed-off-by: Tom Cosgrove --- .../psasim/src/psa_functions_codes.h | 2 + .../psasim/src/psa_sim_crypto_client.c | 196 ++++++++++++++ .../psasim/src/psa_sim_crypto_server.c | 250 ++++++++++++++++++ .../psasim/src/psa_sim_generate.pl | 122 +++++++++ 4 files changed, 570 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 1e5739fac7..fbbdea2db8 100644 --- a/tests/psa-client-server/psasim/src/psa_functions_codes.h +++ b/tests/psa-client-server/psasim/src/psa_functions_codes.h @@ -24,6 +24,8 @@ enum { PSA_AEAD_UPDATE, PSA_AEAD_UPDATE_AD, PSA_AEAD_VERIFY, + PSA_ASYMMETRIC_DECRYPT, + PSA_ASYMMETRIC_ENCRYPT, PSA_CIPHER_ABORT, PSA_CIPHER_DECRYPT, PSA_CIPHER_DECRYPT_SETUP, 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 8be8b073b7..8dd85a317f 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 @@ -1133,6 +1133,202 @@ fail: } +psa_status_t psa_asymmetric_decrypt( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + const uint8_t *salt, size_t salt_length, + uint8_t *output, size_t output_size, + size_t *output_length + ) +{ + 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_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(salt, salt_length) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(*output_length); + + 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_mbedtls_svc_key_id_t(&pos, &remaining, key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer(&pos, &remaining, input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer(&pos, &remaining, salt, salt_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer(&pos, &remaining, output, output_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t(&pos, &remaining, *output_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_ASYMMETRIC_DECRYPT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_ASYMMETRIC_DECRYPT 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_return_buffer(&rpos, &rremain, output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t(&rpos, &rremain, output_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + +psa_status_t psa_asymmetric_encrypt( + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + const uint8_t *salt, size_t salt_length, + uint8_t *output, size_t output_size, + size_t *output_length + ) +{ + 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_mbedtls_svc_key_id_t_needs(key) + + psasim_serialise_psa_algorithm_t_needs(alg) + + psasim_serialise_buffer_needs(input, input_length) + + psasim_serialise_buffer_needs(salt, salt_length) + + psasim_serialise_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(*output_length); + + 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_mbedtls_svc_key_id_t(&pos, &remaining, key); + if (!ok) { + goto fail; + } + ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer(&pos, &remaining, input, input_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer(&pos, &remaining, salt, salt_length); + if (!ok) { + goto fail; + } + ok = psasim_serialise_buffer(&pos, &remaining, output, output_size); + if (!ok) { + goto fail; + } + ok = psasim_serialise_size_t(&pos, &remaining, *output_length); + if (!ok) { + goto fail; + } + + ok = psa_crypto_call(PSA_ASYMMETRIC_ENCRYPT, + ser_params, (size_t) (pos - ser_params), &ser_result, &result_length); + if (!ok) { + printf("PSA_ASYMMETRIC_ENCRYPT 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_return_buffer(&rpos, &rremain, output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t(&rpos, &rremain, output_length); + if (!ok) { + goto fail; + } + +fail: + free(ser_params); + free(ser_result); + + return status; +} + + psa_status_t psa_cipher_abort( psa_cipher_operation_t *operation ) 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 7ad0d67750..ae803491ea 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 @@ -1261,6 +1261,248 @@ fail: return 0; // This shouldn't happen! } +// Returns 1 for success, 0 for failure +int psa_asymmetric_decrypt_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; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *input = NULL; + size_t input_length; + uint8_t *salt = NULL; + size_t salt_length; + uint8_t *output = NULL; + size_t output_size; + size_t output_length; + + 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_mbedtls_svc_key_id_t(&pos, &remaining, &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer(&pos, &remaining, &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer(&pos, &remaining, &salt, &salt_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer(&pos, &remaining, &output, &output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t(&pos, &remaining, &output_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_asymmetric_decrypt( + key, + alg, + input, input_length, + salt, salt_length, + output, output_size, + &output_length + ); + + // 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_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(output_length); + + 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_buffer(&rpos, &rremain, output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t(&rpos, &rremain, output_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(salt); + free(output); + + return 1; // success + +fail: + free(result); + + free(input); + free(salt); + free(output); + + return 0; // This shouldn't happen! +} + +// Returns 1 for success, 0 for failure +int psa_asymmetric_encrypt_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; + mbedtls_svc_key_id_t key; + psa_algorithm_t alg; + uint8_t *input = NULL; + size_t input_length; + uint8_t *salt = NULL; + size_t salt_length; + uint8_t *output = NULL; + size_t output_size; + size_t output_length; + + 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_mbedtls_svc_key_id_t(&pos, &remaining, &key); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer(&pos, &remaining, &input, &input_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer(&pos, &remaining, &salt, &salt_length); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_buffer(&pos, &remaining, &output, &output_size); + if (!ok) { + goto fail; + } + + ok = psasim_deserialise_size_t(&pos, &remaining, &output_length); + if (!ok) { + goto fail; + } + + // Now we call the actual target function + + status = psa_asymmetric_encrypt( + key, + alg, + input, input_length, + salt, salt_length, + output, output_size, + &output_length + ); + + // 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_buffer_needs(output, output_size) + + psasim_serialise_size_t_needs(output_length); + + 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_buffer(&rpos, &rremain, output, output_size); + if (!ok) { + goto fail; + } + + ok = psasim_serialise_size_t(&rpos, &rremain, output_length); + if (!ok) { + goto fail; + } + + *out_params = result; + *out_params_len = result_size; + + free(input); + free(salt); + free(output); + + return 1; // success + +fail: + free(result); + + free(input); + free(salt); + free(output); + + return 0; // This shouldn't happen! +} + // Returns 1 for success, 0 for failure int psa_cipher_abort_wrapper( uint8_t *in_params, size_t in_params_len, @@ -5474,6 +5716,14 @@ psa_status_t psa_crypto_call(psa_msg_t msg) ok = psa_aead_verify_wrapper(in_params, in_params_len, &out_params, &out_params_len); break; + case PSA_ASYMMETRIC_DECRYPT: + ok = psa_asymmetric_decrypt_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; + case PSA_ASYMMETRIC_ENCRYPT: + ok = psa_asymmetric_encrypt_wrapper(in_params, in_params_len, + &out_params, &out_params_len); + break; case PSA_CIPHER_ABORT: ok = psa_cipher_abort_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 e641433644..82a6249f3b 100755 --- a/tests/psa-client-server/psasim/src/psa_sim_generate.pl +++ b/tests/psa-client-server/psasim/src/psa_sim_generate.pl @@ -4524,3 +4524,125 @@ psa_status_t psa_verify_hash(mbedtls_svc_key_id_t key, size_t hash_length, const uint8_t *signature, size_t signature_length); + +/** + * \brief Encrypt a short message with a public key. + * + * \param key Identifier of the key to use for the operation. + * It must be a public key or an asymmetric key + * pair. It must allow the usage + * #PSA_KEY_USAGE_ENCRYPT. + * \param alg An asymmetric encryption algorithm that is + * compatible with the type of \p key. + * \param[in] input The message to encrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] salt A salt or label, if supported by the + * encryption algorithm. + * If the algorithm does not support a + * salt, pass \c NULL. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass \c NULL. + * + * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param salt_length Size of the \p salt buffer in bytes. + * If \p salt is \c NULL, pass 0. + * \param[out] output Buffer where the encrypted message is to + * be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p key. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \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_asymmetric_encrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** + * \brief Decrypt a short message with a private key. + * + * \param key Identifier of the key to use for the operation. + * It must be an asymmetric key pair. It must + * allow the usage #PSA_KEY_USAGE_DECRYPT. + * \param alg An asymmetric encryption algorithm that is + * compatible with the type of \p key. + * \param[in] input The message to decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] salt A salt or label, if supported by the + * encryption algorithm. + * If the algorithm does not support a + * salt, pass \c NULL. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass \c NULL. + * + * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param salt_length Size of the \p salt buffer in bytes. + * If \p salt is \c NULL, pass 0. + * \param[out] output Buffer where the decrypted message is to + * be written. + * \param output_size Size of the \c output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p key. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_INVALID_PADDING \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_asymmetric_decrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length);