From 17845b8f7119ee512ed98be423231ad87c61eccf Mon Sep 17 00:00:00 2001 From: Aditya Deshpande Date: Thu, 13 Oct 2022 17:21:01 +0100 Subject: [PATCH] Add driver wrapper function for raw key agreement, along with test call for transparent drivers. Signed-off-by: Aditya Deshpande --- library/psa_crypto.c | 58 +++++++++++---- library/psa_crypto_core.h | 58 +++++++++++++++ library/psa_crypto_driver_wrappers.h | 16 ++++ .../psa_crypto_driver_wrappers.c.jinja | 64 ++++++++++++++++ tests/include/test/drivers/key_agreement.h | 71 ++++++++++++++++++ tests/include/test/drivers/test_driver.h | 1 + tests/src/drivers/test_driver_key_agreement.c | 73 +++++++++++++++++++ 7 files changed, 328 insertions(+), 13 deletions(-) create mode 100644 tests/include/test/drivers/key_agreement.h create mode 100644 tests/src/drivers/test_driver_key_agreement.c diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 2ce5e4320d..194d986b2f 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -5793,26 +5793,28 @@ exit: #define PSA_KEY_AGREEMENT_MAX_SHARED_SECRET_SIZE MBEDTLS_ECP_MAX_BYTES -static psa_status_t psa_key_agreement_raw_internal( psa_algorithm_t alg, - psa_key_slot_t *private_key, - const uint8_t *peer_key, - size_t peer_key_length, - uint8_t *shared_secret, - size_t shared_secret_size, - size_t *shared_secret_length ) +psa_status_t psa_key_agreement_raw_builtin( const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length ) { switch( alg ) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) case PSA_ALG_ECDH: - if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( private_key->attr.type ) ) + if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( attributes->core.type ) ) return( PSA_ERROR_INVALID_ARGUMENT ); mbedtls_ecp_keypair *ecp = NULL; psa_status_t status = mbedtls_psa_ecp_load_representation( - private_key->attr.type, - private_key->attr.bits, - private_key->key.data, - private_key->key.bytes, + attributes->core.type, + attributes->core.bits, + key_buffer, + key_buffer_size, &ecp ); if( status != PSA_SUCCESS ) return( status ); @@ -5825,7 +5827,9 @@ static psa_status_t psa_key_agreement_raw_internal( psa_algorithm_t alg, return( status ); #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */ default: - (void) private_key; + (void) attributes; + (void) key_buffer; + (void) key_buffer_size; (void) peer_key; (void) peer_key_length; (void) shared_secret; @@ -5835,6 +5839,34 @@ static psa_status_t psa_key_agreement_raw_internal( psa_algorithm_t alg, } } +/** Internal function for raw key agreement + * Calls the driver wrapper which will hand off key agreement task + * to the driver's implementation if a driver is present. + * Fallback specified in the driver wrapper is built-in raw key agreement + * (psa_key_agreement_raw_builtin). + */ +static psa_status_t psa_key_agreement_raw_internal( psa_algorithm_t alg, + psa_key_slot_t *private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length ) +{ + if( !PSA_ALG_IS_RAW_KEY_AGREEMENT(alg) ) + return( PSA_ERROR_NOT_SUPPORTED ); + + psa_key_attributes_t attributes = { + .core = private_key->attr + }; + + return( psa_driver_wrapper_key_agreement( &attributes, private_key->key.data, + private_key->key.bytes, + alg, peer_key, peer_key_length, + shared_secret, shared_secret_size, + shared_secret_length ) ); +} + /* Note that if this function fails, you must call psa_key_derivation_abort() * to potentially free embedded data structures and wipe confidential data. */ diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index 8c91b04d03..5bfdfb39ea 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -547,4 +547,62 @@ psa_status_t psa_verify_hash_builtin( */ psa_status_t psa_validate_unstructured_key_bit_size( psa_key_type_t type, size_t bits ); + +/** Perform a key agreement and return the raw shared secret, using + built-in raw key agreement functions. + * + * \note The signature of this function is that of a PSA driver + * key_agreement entry point. This function behaves as a key_agreement + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in] attributes The attributes of the key to use for + * the operation. + * \param[in] key_buffer The buffer containing the private key + * context. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in + * bytes. + * \param[in] alg A key agreement algorithm that is + * compatible with the type of the key. + * \param[in] peer_key The buffer containing the key context + * of the peer's public key. + * \param[in] peer_key_length Size of the \p peer_key buffer in + * bytes. + * \param[out] shared_secret The buffer to which the shared secret + * is to be written. + * \param[in] shared_secret_size Size of the \p shared_secret buffer in + * bytes. + * \param[out] shared_secret_length On success, the number of bytes that + * make up the returned shared secret. + * \retval #PSA_SUCCESS + * Success. Shared secret successfully calculated. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p alg is not a key agreement algorithm, or + * \p private_key is not compatible with \p alg, + * or \p peer_key is not valid for \p alg or not compatible with + * \p private_key. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p shared_secret_size is too small + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not a supported key agreement algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + */ +psa_status_t psa_key_agreement_raw_builtin( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length ); + #endif /* PSA_CRYPTO_CORE_H */ diff --git a/library/psa_crypto_driver_wrappers.h b/library/psa_crypto_driver_wrappers.h index ee23b6f3fe..017a4b6c88 100644 --- a/library/psa_crypto_driver_wrappers.h +++ b/library/psa_crypto_driver_wrappers.h @@ -357,6 +357,22 @@ psa_status_t psa_driver_wrapper_asymmetric_decrypt( size_t output_size, size_t *output_length ); +/* + * Raw Key Agreement + */ + + psa_status_t psa_driver_wrapper_key_agreement( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length + ); + #endif /* PSA_CRYPTO_DRIVER_WRAPPERS_H */ /* End of automatically generated file. */ diff --git a/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja b/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja index 8ef2e6d874..734b6b6861 100644 --- a/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja +++ b/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja @@ -2452,4 +2452,68 @@ psa_status_t psa_driver_wrapper_asymmetric_decrypt( } } +psa_status_t psa_driver_wrapper_key_agreement( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length + ) + { + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ + #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + #if defined(PSA_CRYPTO_DRIVER_TEST) + status = + mbedtls_test_transparent_key_agreement( attributes, + key_buffer, + key_buffer_size, + alg, + peer_key, + peer_key_length, + shared_secret, + shared_secret_size, + shared_secret_length ); + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); + #endif /* PSA_CRYPTO_DRIVER_TEST */ + #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + /* Software Fallback */ + status = psa_key_agreement_raw_builtin( attributes, + key_buffer, + key_buffer_size, + alg, + peer_key, + peer_key_length, + shared_secret, + shared_secret_size, + shared_secret_length ); + return( status ); + + default: + (void) attributes; + (void) key_buffer; + (void) key_buffer_size; + (void) peer_key; + (void) peer_key_length; + (void) shared_secret; + (void) shared_secret_size; + (void) shared_secret_length; + return( PSA_ERROR_NOT_SUPPORTED ); + + } + } + #endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/tests/include/test/drivers/key_agreement.h b/tests/include/test/drivers/key_agreement.h new file mode 100644 index 0000000000..57de81ab1f --- /dev/null +++ b/tests/include/test/drivers/key_agreement.h @@ -0,0 +1,71 @@ +/* + * Test driver for key agreement functions. + */ +/* Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PSA_CRYPTO_TEST_DRIVERS_KEY_AGREEMENT_H +#define PSA_CRYPTO_TEST_DRIVERS_KEY_AGREEMENT_H + +#include "mbedtls/build_info.h" + +#if defined(PSA_CRYPTO_DRIVER_TEST) +#include + +typedef struct { + /* If non-null, on success, copy this to the output. */ + void *forced_output; + size_t forced_output_length; + /* If not PSA_SUCCESS, return this error code instead of processing the + * function call. */ + psa_status_t forced_status; + /* Count the amount of times one of the signature driver functions is called. */ + unsigned long hits; +} mbedtls_test_driver_key_agreement_hooks_t; + +#define MBEDTLS_TEST_DRIVER_KEY_AGREEMENT_INIT { NULL, 0, PSA_SUCCESS, 0 } +static inline mbedtls_test_driver_key_agreement_hooks_t + mbedtls_test_driver_key_agreement_hooks_init( void ) +{ + const mbedtls_test_driver_key_agreement_hooks_t + v = MBEDTLS_TEST_DRIVER_KEY_AGREEMENT_INIT; + return( v ); +} + +psa_status_t mbedtls_test_transparent_key_agreement( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length ); + +psa_status_t mbedtls_test_opaque_key_agreement( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length ); + +#endif /*PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_TEST_DRIVERS_KEY_AGREEMENT_H */ \ No newline at end of file diff --git a/tests/include/test/drivers/test_driver.h b/tests/include/test/drivers/test_driver.h index 098b21abff..0bfeb66b03 100644 --- a/tests/include/test/drivers/test_driver.h +++ b/tests/include/test/drivers/test_driver.h @@ -29,5 +29,6 @@ #include "test/drivers/key_management.h" #include "test/drivers/signature.h" #include "test/drivers/asymmetric_encryption.h" +#include "test/drivers/key_agreement.h" #endif /* PSA_CRYPTO_TEST_DRIVER_H */ diff --git a/tests/src/drivers/test_driver_key_agreement.c b/tests/src/drivers/test_driver_key_agreement.c new file mode 100644 index 0000000000..40681c315b --- /dev/null +++ b/tests/src/drivers/test_driver_key_agreement.c @@ -0,0 +1,73 @@ +/* + * Test driver for key agreement functions. + */ +/* Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "psa/crypto.h" +#include "psa_crypto_core.h" + +#include "test/drivers/key_agreement.h" +#include "test/drivers/test_driver.h" + +#include + +#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST) + +mbedtls_test_driver_key_agreement_hooks_t + mbedtls_test_driver_key_agreement_hooks = MBEDTLS_TEST_DRIVER_KEY_AGREEMENT_INIT; + +psa_status_t mbedtls_test_transparent_key_agreement( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length ) +{ + if( mbedtls_test_driver_key_agreement_hooks.forced_status != PSA_SUCCESS ) + return( mbedtls_test_driver_key_agreement_hooks.forced_status ); + + if( mbedtls_test_driver_key_agreement_hooks.forced_output != NULL ) + { + if( mbedtls_test_driver_key_agreement_hooks.forced_output_length > shared_secret_size ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + memcpy( shared_secret, mbedtls_test_driver_key_agreement_hooks.forced_output, + mbedtls_test_driver_key_agreement_hooks.forced_output_length ); + *shared_secret_length = mbedtls_test_driver_key_agreement_hooks.forced_output_length; + + return( PSA_SUCCESS ); + } + + return( psa_key_agreement_raw_builtin( + attributes, + key_buffer, + key_buffer_size, + alg, + peer_key, + peer_key_length, + shared_secret, + shared_secret_size, + shared_secret_length ) ); +} + +#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */ \ No newline at end of file