diff --git a/CMakeLists.txt b/CMakeLists.txt index 88332464bf..5af4c8124f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -261,7 +261,7 @@ add_subdirectory(library) # to define the test executables. # if(ENABLE_TESTING OR ENABLE_PROGRAMS) - file(GLOB MBEDTLS_TEST_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/*.c) + file(GLOB MBEDTLS_TEST_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/*.c ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/drivers/*.c) add_library(mbedtls_test OBJECT ${MBEDTLS_TEST_FILES}) target_include_directories(mbedtls_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests/include diff --git a/ChangeLog.d/add_sign_verify_keygen_transparent_driver.txt b/ChangeLog.d/add_sign_verify_keygen_transparent_driver.txt new file mode 100644 index 0000000000..fe43899923 --- /dev/null +++ b/ChangeLog.d/add_sign_verify_keygen_transparent_driver.txt @@ -0,0 +1,4 @@ +Features + * Partial implementation of the new PSA Crypto accelerator APIs for + enabling key generation and asymmetric signing/verification through crypto + accelerators. Contributed by Steven Cooreman in #3501. diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 1e6e052756..a2f408f2d1 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -1329,6 +1329,17 @@ */ #define MBEDTLS_PKCS1_V21 +/** \def MBEDTLS_PSA_CRYPTO_DRIVERS + * + * Enable support for the experimental PSA crypto driver interface. + * + * Requires: MBEDTLS_PSA_CRYPTO_C. + * + * \warning This interface is experimental and may change or be removed + * without notice. + */ +//#define MBEDTLS_PSA_CRYPTO_DRIVERS + /** * \def MBEDTLS_PSA_CRYPTO_SPM * diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 33e2cfc855..91ac8bc7e0 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -61,6 +61,7 @@ set(src_crypto platform_util.c poly1305.c psa_crypto.c + psa_crypto_driver_wrappers.c psa_crypto_se.c psa_crypto_slot_management.c psa_crypto_storage.c diff --git a/library/Makefile b/library/Makefile index b76a84bdd2..c7d4a0615f 100644 --- a/library/Makefile +++ b/library/Makefile @@ -118,6 +118,7 @@ OBJS_CRYPTO= \ platform_util.o \ poly1305.o \ psa_crypto.o \ + psa_crypto_driver_wrappers.o \ psa_crypto_se.o \ psa_crypto_slot_management.o \ psa_crypto_storage.o \ diff --git a/library/psa_crypto.c b/library/psa_crypto.c index bffddc995b..77e63045a7 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -27,6 +27,7 @@ #include "psa_crypto_core.h" #include "psa_crypto_invasive.h" +#include "psa_crypto_driver_wrappers.h" #if defined(MBEDTLS_PSA_CRYPTO_SE_C) #include "psa_crypto_se.h" #endif @@ -124,7 +125,7 @@ static psa_global_data_t global_data; if( global_data.initialized == 0 ) \ return( PSA_ERROR_BAD_STATE ); -static psa_status_t mbedtls_to_psa_error( int ret ) +psa_status_t mbedtls_to_psa_error( int ret ) { /* If there's both a high-level code and low-level code, dispatch on * the high-level code. */ @@ -3637,10 +3638,6 @@ psa_status_t psa_sign_hash( psa_key_handle_t handle, { psa_key_slot_t *slot; psa_status_t status; -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - const psa_drv_se_t *drv; - psa_drv_se_context_t *drv_context; -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ *signature_length = signature_size; /* Immediately reject a zero-length signature buffer. This guarantees @@ -3659,24 +3656,19 @@ psa_status_t psa_sign_hash( psa_key_handle_t handle, goto exit; } -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) - { - if( drv->asymmetric == NULL || - drv->asymmetric->p_sign == NULL ) - { - status = PSA_ERROR_NOT_SUPPORTED; - goto exit; - } - status = drv->asymmetric->p_sign( drv_context, - slot->data.se.slot_number, - alg, - hash, hash_length, - signature, signature_size, - signature_length ); - } - else -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + /* Try any of the available accelerators first */ + status = psa_driver_wrapper_sign_hash( slot, + alg, + hash, + hash_length, + signature, + signature_size, + signature_length ); + if( status != PSA_ERROR_NOT_SUPPORTED || + psa_key_lifetime_is_external( slot->attr.lifetime ) ) + goto exit; + + /* If the operation was not supported by any accelerator, try fallback. */ #if defined(MBEDTLS_RSA_C) if( slot->attr.type == PSA_KEY_TYPE_RSA_KEY_PAIR ) { @@ -3763,29 +3755,22 @@ psa_status_t psa_verify_hash( psa_key_handle_t handle, { psa_key_slot_t *slot; psa_status_t status; -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - const psa_drv_se_t *drv; - psa_drv_se_context_t *drv_context; -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_VERIFY_HASH, alg ); if( status != PSA_SUCCESS ) return( status ); -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) - { - if( drv->asymmetric == NULL || - drv->asymmetric->p_verify == NULL ) - return( PSA_ERROR_NOT_SUPPORTED ); - return( drv->asymmetric->p_verify( drv_context, - slot->data.se.slot_number, - alg, - hash, hash_length, - signature, signature_length ) ); - } - else -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + /* Try any of the available accelerators first */ + status = psa_driver_wrapper_verify_hash( slot, + alg, + hash, + hash_length, + signature, + signature_length ); + if( status != PSA_ERROR_NOT_SUPPORTED || + psa_key_lifetime_is_external( slot->attr.lifetime ) ) + return status; + #if defined(MBEDTLS_RSA_C) if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) { @@ -6004,29 +5989,15 @@ psa_status_t psa_generate_key( const psa_key_attributes_t *attributes, if( status != PSA_SUCCESS ) goto exit; -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( driver != NULL ) - { - const psa_drv_se_t *drv = psa_get_se_driver_methods( driver ); - size_t pubkey_length = 0; /* We don't support this feature yet */ - if( drv->key_management == NULL || - drv->key_management->p_generate == NULL ) - { - status = PSA_ERROR_NOT_SUPPORTED; - goto exit; - } - status = drv->key_management->p_generate( - psa_get_se_driver_context( driver ), - slot->data.se.slot_number, attributes, - NULL, 0, &pubkey_length ); - } - else -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - { - status = psa_generate_key_internal( - slot, attributes->core.bits, - attributes->domain_parameters, attributes->domain_parameters_size ); - } + status = psa_driver_wrapper_generate_key( attributes, + slot ); + if( status != PSA_ERROR_NOT_SUPPORTED || + psa_key_lifetime_is_external( attributes->core.lifetime ) ) + goto exit; + + status = psa_generate_key_internal( + slot, attributes->core.bits, + attributes->domain_parameters, attributes->domain_parameters_size ); exit: if( status == PSA_SUCCESS ) diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index 9a61babb50..6ee17fce06 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -161,4 +161,16 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, const uint8_t *data, size_t data_length ); + +/** Convert an mbed TLS error code to a PSA error code + * + * \note This function is provided solely for the convenience of + * Mbed TLS and may be removed at any time without notice. + * + * \param ret An mbed TLS-thrown error code + * + * \return The corresponding PSA error code + */ +psa_status_t mbedtls_to_psa_error( int ret ); + #endif /* PSA_CRYPTO_CORE_H */ diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c new file mode 100644 index 0000000000..cc51e2450e --- /dev/null +++ b/library/psa_crypto_driver_wrappers.c @@ -0,0 +1,373 @@ +/* + * Functions to delegate cryptographic operations to an available + * and appropriate accelerator. + * Warning: This file will be auto-generated in the future. + */ +/* 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 "psa_crypto_core.h" +#include "psa_crypto_driver_wrappers.h" +#include "mbedtls/platform.h" + +#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) + +/* Include test driver definition when running tests */ +#if defined(PSA_CRYPTO_DRIVER_TEST) +#ifndef PSA_CRYPTO_DRIVER_PRESENT +#define PSA_CRYPTO_DRIVER_PRESENT +#endif +#ifndef PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT +#define PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT +#endif +#include "test/drivers/test_driver.h" +#endif /* PSA_CRYPTO_DRIVER_TEST */ + +/* Repeat above block for each JSON-declared driver during autogeneration */ + +#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */ + +/* Support the 'old' SE interface when asked to */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +/* PSA_CRYPTO_DRIVER_PRESENT is defined when either a new-style or old-style + * SE driver is present, to avoid unused argument errors at compile time. */ +#ifndef PSA_CRYPTO_DRIVER_PRESENT +#define PSA_CRYPTO_DRIVER_PRESENT +#endif +#include "psa_crypto_se.h" +#endif + +/* Start delegation functions */ +psa_status_t psa_driver_wrapper_sign_hash( psa_key_slot_t *slot, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) + { + if( drv->asymmetric == NULL || + drv->asymmetric->p_sign == NULL ) + { + /* Key is defined in SE, but we have no way to exercise it */ + return( PSA_ERROR_NOT_SUPPORTED ); + } + return( drv->asymmetric->p_sign( drv_context, + slot->data.se.slot_number, + alg, + hash, hash_length, + signature, signature_size, + signature_length ) ); + } +#endif /* PSA_CRYPTO_SE_C */ + + /* Then try accelerator API */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime); + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + 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_DRIVER_TEST) + status = test_transparent_signature_sign_hash( &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg, + hash, + hash_length, + signature, + signature_size, + signature_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + /* Fell through, meaning no accelerator supports this operation */ + return( PSA_ERROR_NOT_SUPPORTED ); + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LIFETIME: + return( test_opaque_signature_sign_hash( &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg, + hash, + hash_length, + signature, + signature_size, + signature_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is declared with a lifetime not known to us */ + return( status ); + } +#else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void)slot; + (void)alg; + (void)hash; + (void)hash_length; + (void)signature; + (void)signature_size; + (void)signature_length; + + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +psa_status_t psa_driver_wrapper_verify_hash( psa_key_slot_t *slot, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) + { + if( drv->asymmetric == NULL || + drv->asymmetric->p_verify == NULL ) + { + /* Key is defined in SE, but we have no way to exercise it */ + return( PSA_ERROR_NOT_SUPPORTED ); + } + return( drv->asymmetric->p_verify( drv_context, + slot->data.se.slot_number, + alg, + hash, hash_length, + signature, signature_length ) ); + } +#endif /* PSA_CRYPTO_SE_C */ + + /* Then try accelerator API */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime); + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + 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_DRIVER_TEST) + status = test_transparent_signature_verify_hash( &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg, + hash, + hash_length, + signature, + signature_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + /* Fell through, meaning no accelerator supports this operation */ + return( PSA_ERROR_NOT_SUPPORTED ); + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LIFETIME: + return( test_opaque_signature_verify_hash( &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg, + hash, + hash_length, + signature, + signature_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is declared with a lifetime not known to us */ + return( status ); + } +#else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void)slot; + (void)alg; + (void)hash; + (void)hash_length; + (void)signature; + (void)signature_length; + + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +/** Calculate the size to allocate for buffering a key with given attributes. + * + * This function provides a way to get the expected size for storing a key with + * the given attributes. This will be the size of the export representation for + * cleartext keys, and a driver-defined size for keys stored by opaque drivers. + * + * \param[in] attributes The key attribute structure of the key to store. + * \param[out] expected_size On success, a byte size large enough to contain + * the declared key. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_NOT_SUPPORTED + */ +static psa_status_t get_expected_key_size( const psa_key_attributes_t *attributes, + size_t *expected_size ) +{ + size_t buffer_size = 0; + if( PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ) == PSA_KEY_LOCATION_LOCAL_STORAGE ) + { + buffer_size = PSA_KEY_EXPORT_MAX_SIZE( attributes->core.type, + attributes->core.bits ); + + if( buffer_size == 0 ) + return( PSA_ERROR_NOT_SUPPORTED ); + + *expected_size = buffer_size; + return( PSA_SUCCESS ); + } + else + { + /* TBD: opaque driver support: need to calculate size through a + * driver-defined size function, since the size of an opaque (wrapped) + * key will be different for each implementation. */ + return( PSA_ERROR_NOT_SUPPORTED ); + } +} +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ + +psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attributes, + psa_key_slot_t *slot ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) + { + size_t pubkey_length = 0; /* We don't support this feature yet */ + if( drv->key_management == NULL || + drv->key_management->p_generate == NULL ) + { + /* Key is defined as being in SE, but we have no way to generate it */ + return( PSA_ERROR_NOT_SUPPORTED ); + } + return( drv->key_management->p_generate( + drv_context, + slot->data.se.slot_number, attributes, + NULL, 0, &pubkey_length ) ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + /* Then try accelerator API */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime); + size_t export_size = 0; + + status = get_expected_key_size( attributes, &export_size ); + if( status != PSA_SUCCESS ) + return( status ); + + slot->data.key.data = mbedtls_calloc(1, export_size); + if( slot->data.key.data == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + slot->data.key.bytes = export_size; + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ + + /* Transparent drivers are limited to generating asymmetric keys */ + if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) ) + { + status = PSA_ERROR_NOT_SUPPORTED; + break; + } +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = test_transparent_generate_key( attributes, + slot->data.key.data, + slot->data.key.bytes, + &slot->data.key.bytes ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + break; +#endif /* PSA_CRYPTO_DRIVER_TEST */ + /* Fell through, meaning no accelerator supports this operation */ + status = PSA_ERROR_NOT_SUPPORTED; + break; + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LIFETIME: + status = test_opaque_generate_key( attributes, + slot->data.key.data, + slot->data.key.bytes, + &slot->data.key.bytes ); + break; +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is declared with a lifetime not known to us */ + status = PSA_ERROR_INVALID_ARGUMENT; + break; + } + + if( status != PSA_SUCCESS ) + { + /* free allocated buffer */ + mbedtls_free( slot->data.key.data ); + slot->data.key.data = NULL; + slot->data.key.bytes = 0; + } + + return( status ); +#else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void) attributes; + (void) slot; + + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +/* End of automatically generated file. */ diff --git a/library/psa_crypto_driver_wrappers.h b/library/psa_crypto_driver_wrappers.h new file mode 100644 index 0000000000..42993792a6 --- /dev/null +++ b/library/psa_crypto_driver_wrappers.h @@ -0,0 +1,48 @@ +/* + * Function signatures for functionality that can be provided by + * cryptographic accelerators. + * Warning: This file will be auto-generated in the future. + */ +/* 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_DRIVER_WRAPPERS_H +#define PSA_CRYPTO_DRIVER_WRAPPERS_H + +#include "psa/crypto.h" +#include "psa/crypto_driver_common.h" + +psa_status_t psa_driver_wrapper_sign_hash( psa_key_slot_t *slot, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length ); + +psa_status_t psa_driver_wrapper_verify_hash( psa_key_slot_t *slot, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length ); + +psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attributes, + psa_key_slot_t *slot ); + +#endif /* PSA_CRYPTO_DRIVER_WRAPPERS_H */ + +/* End of automatically generated file. */ diff --git a/library/version_features.c b/library/version_features.c index d2840fa3cd..051fb1953f 100644 --- a/library/version_features.c +++ b/library/version_features.c @@ -435,6 +435,9 @@ static const char * const features[] = { #if defined(MBEDTLS_PKCS1_V21) "MBEDTLS_PKCS1_V21", #endif /* MBEDTLS_PKCS1_V21 */ +#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) + "MBEDTLS_PSA_CRYPTO_DRIVERS", +#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */ #if defined(MBEDTLS_PSA_CRYPTO_SPM) "MBEDTLS_PSA_CRYPTO_SPM", #endif /* MBEDTLS_PSA_CRYPTO_SPM */ diff --git a/programs/Makefile b/programs/Makefile index f9c260867b..dfe0555692 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -8,7 +8,7 @@ WARNING_CXXFLAGS ?= -Wall -Wextra LDFLAGS ?= MBEDTLS_TEST_PATH:=../tests/src -MBEDTLS_TEST_OBJS:=$(patsubst %.c,%.o,$(wildcard ${MBEDTLS_TEST_PATH}/*.c)) +MBEDTLS_TEST_OBJS:=$(patsubst %.c,%.o,$(wildcard ${MBEDTLS_TEST_PATH}/*.c ${MBEDTLS_TEST_PATH}/drivers/*.c)) LOCAL_CFLAGS = $(WARNING_CFLAGS) -I../tests/include -I../include -D_FILE_OFFSET_BITS=64 LOCAL_CXXFLAGS = $(WARNING_CXXFLAGS) -I../include -D_FILE_OFFSET_BITS=64 diff --git a/programs/fuzz/Makefile b/programs/fuzz/Makefile index 8196f39303..fa17918fad 100644 --- a/programs/fuzz/Makefile +++ b/programs/fuzz/Makefile @@ -1,5 +1,5 @@ MBEDTLS_TEST_PATH:=../../tests/src -MBEDTLS_TEST_OBJS:=$(patsubst %.c,%.o,$(wildcard ${MBEDTLS_TEST_PATH}/*.c)) +MBEDTLS_TEST_OBJS:=$(patsubst %.c,%.o,$(wildcard ${MBEDTLS_TEST_PATH}/*.c ${MBEDTLS_TEST_PATH}/drivers/*.c)) LOCAL_CFLAGS = -I../../tests/include -I../../include -D_FILE_OFFSET_BITS=64 LOCAL_LDFLAGS = ${MBEDTLS_TEST_OBJS} \ diff --git a/programs/test/query_config.c b/programs/test/query_config.c index f4c14d6cb1..f64eb887b3 100644 --- a/programs/test/query_config.c +++ b/programs/test/query_config.c @@ -1216,6 +1216,14 @@ int query_config( const char *config ) } #endif /* MBEDTLS_PKCS1_V21 */ +#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) + if( strcmp( "MBEDTLS_PSA_CRYPTO_DRIVERS", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PSA_CRYPTO_DRIVERS ); + return( 0 ); + } +#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */ + #if defined(MBEDTLS_PSA_CRYPTO_SPM) if( strcmp( "MBEDTLS_PSA_CRYPTO_SPM", config ) == 0 ) { diff --git a/scripts/generate_visualc_files.pl b/scripts/generate_visualc_files.pl index 3d4baca41e..6c2b5e4ab6 100755 --- a/scripts/generate_visualc_files.pl +++ b/scripts/generate_visualc_files.pl @@ -39,6 +39,7 @@ my $psa_header_dir = 'include/psa'; my $source_dir = 'library'; my $test_source_dir = 'tests/src'; my $test_header_dir = 'tests/include/test'; +my $test_drivers_header_dir = 'tests/include/test/drivers'; my @thirdparty_header_dirs = qw( 3rdparty/everest/include/everest @@ -116,6 +117,7 @@ sub check_dirs { && -d $source_dir && -d $test_source_dir && -d $test_header_dir + && -d $test_drivers_header_dir && -d $programs_dir; } @@ -262,6 +264,7 @@ sub main { $mbedtls_header_dir, $psa_header_dir, $test_header_dir, + $test_drivers_header_dir, $source_dir, @thirdparty_header_dirs, ); diff --git a/tests/.gitignore b/tests/.gitignore index d49611c1eb..d9f4b51787 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -11,4 +11,5 @@ data_files/entropy_seed include/test/instrument_record_status.h src/*.o +src/drivers/*.o src/libmbed* diff --git a/tests/Makefile b/tests/Makefile index ffa4812bdc..511db9db50 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -80,7 +80,7 @@ all: $(BINARIES) $(MBEDLIBS): $(MAKE) -C ../library -MBEDTLS_TEST_OBJS=$(patsubst %.c,%.o,$(wildcard src/*.c)) +MBEDTLS_TEST_OBJS=$(patsubst %.c,%.o,$(wildcard src/*.c src/drivers/*.c)) mbedtls_test: $(MBEDTLS_TEST_OBJS) @@ -89,6 +89,10 @@ src/%.o : src/%.c echo " CC $<" $(CC) $(LOCAL_CFLAGS) $(CFLAGS) -o $@ -c $< +src/drivers/%.o : src/drivers/%.c + echo " CC $<" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) -o $@ -c $< + C_FILES := $(addsuffix .c,$(APPS)) # Wildcard target for test code generation: @@ -130,12 +134,13 @@ $(addprefix embedded_,$(filter test_suite_psa_%, $(APPS))): embedded_%: TESTS/mb clean: ifndef WINDOWS rm -rf $(BINARIES) *.c *.datax TESTS - rm -f src/*.o src/libmbed* + rm -f src/*.o src/drivers/*.o src/libmbed* else if exist *.c del /Q /F *.c if exist *.exe del /Q /F *.exe if exist *.datax del /Q /F *.datax if exist src/*.o del /Q /F src/*.o + if exist src/drivers/*.o del /Q /F src/drivers/*.o if exist src/libmbed* del /Q /F src/libmed* ifneq ($(wildcard TESTS/.*),) rmdir /Q /S TESTS diff --git a/tests/include/test/drivers/keygen.h b/tests/include/test/drivers/keygen.h new file mode 100644 index 0000000000..b72c65c78c --- /dev/null +++ b/tests/include/test/drivers/keygen.h @@ -0,0 +1,61 @@ +/* + * Test driver for generating keys. + */ +/* 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_KEYGEN_H +#define PSA_CRYPTO_TEST_DRIVERS_KEYGEN_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#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 keygen driver functions is called. */ + unsigned long hits; +} test_driver_keygen_hooks_t; + +#define TEST_DRIVER_KEYGEN_INIT { NULL, 0, PSA_ERROR_NOT_SUPPORTED, 0 } +static inline test_driver_keygen_hooks_t test_driver_keygen_hooks_init( void ) +{ + const test_driver_keygen_hooks_t v = TEST_DRIVER_KEYGEN_INIT; + return( v ); +} + +extern test_driver_keygen_hooks_t test_driver_keygen_hooks; + +psa_status_t test_transparent_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key, size_t key_size, size_t *key_length ); + +psa_status_t test_opaque_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key, size_t key_size, size_t *key_length ); + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_TEST_DRIVERS_KEYGEN_H */ diff --git a/tests/include/test/drivers/signature.h b/tests/include/test/drivers/signature.h new file mode 100644 index 0000000000..e41892e77a --- /dev/null +++ b/tests/include/test/drivers/signature.h @@ -0,0 +1,82 @@ +/* + * Test driver for signature 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_SIGNATURE_H +#define PSA_CRYPTO_TEST_DRIVERS_SIGNATURE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#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 keygen driver functions is called. */ + unsigned long hits; +} test_driver_signature_hooks_t; + +#define TEST_DRIVER_SIGNATURE_INIT { NULL, 0, PSA_ERROR_NOT_SUPPORTED, 0 } +static inline test_driver_signature_hooks_t test_driver_signature_hooks_init( void ) +{ + const test_driver_signature_hooks_t v = TEST_DRIVER_SIGNATURE_INIT; + return( v ); +} + +extern test_driver_signature_hooks_t test_driver_signature_sign_hooks; +extern test_driver_signature_hooks_t test_driver_signature_verify_hooks; + +psa_status_t test_transparent_signature_sign_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + uint8_t *signature, size_t signature_size, size_t *signature_length ); + +psa_status_t test_opaque_signature_sign_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + uint8_t *signature, size_t signature_size, size_t *signature_length ); + +psa_status_t test_transparent_signature_verify_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length ); + +psa_status_t test_opaque_signature_verify_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length ); + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_TEST_DRIVERS_SIGNATURE_H */ diff --git a/tests/include/test/drivers/test_driver.h b/tests/include/test/drivers/test_driver.h new file mode 100644 index 0000000000..75135e0f42 --- /dev/null +++ b/tests/include/test/drivers/test_driver.h @@ -0,0 +1,28 @@ +/* + * Umbrella include for all of the test driver functionality + */ +/* 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_DRIVER_H +#define PSA_CRYPTO_TEST_DRIVER_H + +#define PSA_CRYPTO_TEST_DRIVER_LIFETIME 0x7fffff + +#include "test/drivers/signature.h" +#include "test/drivers/keygen.h" + +#endif /* PSA_CRYPTO_TEST_DRIVER_H */ diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index 4fafe0208e..596e1a96a9 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -1656,6 +1656,16 @@ component_test_se_default () { make test } +component_test_psa_crypto_drivers () { + msg "build: MBEDTLS_PSA_CRYPTO_DRIVERS w/ driver hooks" + scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS + # Need to define the correct symbol and include the test driver header path in order to build with the test driver + make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS" + + msg "test: MBEDTLS_PSA_CRYPTO_DRIVERS, signature" + make test +} + component_test_make_shared () { msg "build/test: make shared" # ~ 40s make SHARED=1 all check diff --git a/tests/src/drivers/keygen.c b/tests/src/drivers/keygen.c new file mode 100644 index 0000000000..f15a4bc9a4 --- /dev/null +++ b/tests/src/drivers/keygen.c @@ -0,0 +1,125 @@ +/* + * Test driver for generating keys. + * Currently only supports generating ECC keys. + */ +/* 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. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST) +#include "psa/crypto.h" +#include "psa_crypto_core.h" +#include "mbedtls/ecp.h" +#include "mbedtls/error.h" + +#include "test/drivers/keygen.h" + +#include "test/random.h" + +#include + +test_driver_keygen_hooks_t test_driver_keygen_hooks = TEST_DRIVER_KEYGEN_INIT; + +psa_status_t test_transparent_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key, size_t key_size, size_t *key_length ) +{ + ++test_driver_keygen_hooks.hits; + + if( test_driver_keygen_hooks.forced_status != PSA_SUCCESS ) + return( test_driver_keygen_hooks.forced_status ); + + if( test_driver_keygen_hooks.forced_output != NULL ) + { + if( test_driver_keygen_hooks.forced_output_length > key_size ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + memcpy( key, test_driver_keygen_hooks.forced_output, + test_driver_keygen_hooks.forced_output_length ); + *key_length = test_driver_keygen_hooks.forced_output_length; + return( PSA_SUCCESS ); + } + + /* Copied from psa_crypto.c */ +#if defined(MBEDTLS_ECP_C) + if ( PSA_KEY_TYPE_IS_ECC( psa_get_key_type( attributes ) ) + && PSA_KEY_TYPE_IS_KEY_PAIR( psa_get_key_type( attributes ) ) ) + { + psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( psa_get_key_type( attributes ) ); + mbedtls_ecp_group_id grp_id = + mbedtls_ecc_group_of_psa( curve, PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) ) ); + const mbedtls_ecp_curve_info *curve_info = + mbedtls_ecp_curve_info_from_grp_id( grp_id ); + mbedtls_ecp_keypair ecp; + mbedtls_test_rnd_pseudo_info rnd_info; + memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) ); + + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + if( attributes->domain_parameters_size != 0 ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( curve_info->bit_size != psa_get_key_bits( attributes ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + mbedtls_ecp_keypair_init( &ecp ); + ret = mbedtls_ecp_gen_key( grp_id, &ecp, + &mbedtls_test_rnd_pseudo_rand, + &rnd_info ); + if( ret != 0 ) + { + mbedtls_ecp_keypair_free( &ecp ); + return( mbedtls_to_psa_error( ret ) ); + } + + /* Make sure to use export representation */ + size_t bytes = PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) ); + if( key_size < bytes ) + { + mbedtls_ecp_keypair_free( &ecp ); + return( PSA_ERROR_BUFFER_TOO_SMALL ); + } + psa_status_t status = mbedtls_to_psa_error( + mbedtls_mpi_write_binary( &ecp.d, key, bytes ) ); + + if( status == PSA_SUCCESS ) + { + *key_length = bytes; + } + + mbedtls_ecp_keypair_free( &ecp ); + return( status ); + } + else +#endif /* MBEDTLS_ECP_C */ + return( PSA_ERROR_NOT_SUPPORTED ); +} + +psa_status_t test_opaque_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key, size_t key_size, size_t *key_length ) +{ + (void) attributes; + (void) key; + (void) key_size; + (void) key_length; + return( PSA_ERROR_NOT_SUPPORTED ); +} + +#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */ diff --git a/tests/src/drivers/signature.c b/tests/src/drivers/signature.c new file mode 100644 index 0000000000..028d24a098 --- /dev/null +++ b/tests/src/drivers/signature.c @@ -0,0 +1,289 @@ +/* + * Test driver for signature functions. + * Currently supports signing and verifying precalculated hashes, using + * only deterministic ECDSA on curves secp256r1, secp384r1 and secp521r1. + */ +/* 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. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST) +#include "psa/crypto.h" +#include "psa_crypto_core.h" +#include "mbedtls/ecp.h" + +#include "test/drivers/signature.h" + +#include "mbedtls/md.h" +#include "mbedtls/ecdsa.h" + +#include "test/random.h" + +#include + +test_driver_signature_hooks_t test_driver_signature_sign_hooks = TEST_DRIVER_SIGNATURE_INIT; +test_driver_signature_hooks_t test_driver_signature_verify_hooks = TEST_DRIVER_SIGNATURE_INIT; + +psa_status_t test_transparent_signature_sign_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + uint8_t *signature, size_t signature_size, size_t *signature_length ) +{ + ++test_driver_signature_sign_hooks.hits; + + if( test_driver_signature_sign_hooks.forced_status != PSA_SUCCESS ) + return( test_driver_signature_sign_hooks.forced_status ); + + if( test_driver_signature_sign_hooks.forced_output != NULL ) + { + if( test_driver_signature_sign_hooks.forced_output_length > signature_size ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + memcpy( signature, test_driver_signature_sign_hooks.forced_output, + test_driver_signature_sign_hooks.forced_output_length ); + *signature_length = test_driver_signature_sign_hooks.forced_output_length; + return( PSA_SUCCESS ); + } + + psa_status_t status = PSA_ERROR_NOT_SUPPORTED; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \ + defined(MBEDTLS_SHA256_C) + if( alg != PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ) ) + return( PSA_ERROR_NOT_SUPPORTED ); + mbedtls_ecp_group_id grp_id; + switch( psa_get_key_type( attributes ) ) + { + case PSA_ECC_CURVE_SECP_R1: + switch( psa_get_key_bits( attributes ) ) + { + case 256: + grp_id = MBEDTLS_ECP_DP_SECP256R1; + break; + case 384: + grp_id = MBEDTLS_ECP_DP_SECP384R1; + break; + case 521: + grp_id = MBEDTLS_ECP_DP_SECP521R1; + break; + default: + return( PSA_ERROR_NOT_SUPPORTED ); + } + break; + default: + return( PSA_ERROR_NOT_SUPPORTED ); + } + + /* Beyond this point, the driver is actually doing the work of + * calculating the signature. */ + + status = PSA_ERROR_GENERIC_ERROR; + int ret = 0; + mbedtls_mpi r, s; + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + mbedtls_ecp_keypair ecp; + mbedtls_ecp_keypair_init( &ecp ); + size_t curve_bytes = PSA_BITS_TO_BYTES( ecp.grp.pbits ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ecp.grp, grp_id ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_point_read_binary( &ecp.grp, &ecp.Q, + key, key_length ) ); + + /* Code adapted from psa_ecdsa_sign() in psa_crypto.c. */ + mbedtls_md_type_t md_alg = MBEDTLS_MD_SHA256; + if( signature_size < 2 * curve_bytes ) + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto cleanup; + } + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ecp.grp, &r, &s, &ecp.d, + hash, hash_length, md_alg ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &r, + signature, + curve_bytes ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &s, + signature + curve_bytes, + curve_bytes ) ); +cleanup: + status = mbedtls_to_psa_error( ret ); + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + mbedtls_ecp_keypair_free( &ecp ); + if( status == PSA_SUCCESS ) + *signature_length = 2 * curve_bytes; +#else /* defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \ + defined(MBEDTLS_SHA256_C) */ + (void) attributes; + (void) key; + (void) key_length; + (void) alg; + (void) hash; + (void) hash_length; +#endif /* defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \ + defined(MBEDTLS_SHA256_C) */ + + return( status ); +} + +psa_status_t test_opaque_signature_sign_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + uint8_t *signature, size_t signature_size, size_t *signature_length ) +{ + (void) attributes; + (void) key; + (void) key_length; + (void) alg; + (void) hash; + (void) hash_length; + (void) signature; + (void) signature_size; + (void) signature_length; + return( PSA_ERROR_NOT_SUPPORTED ); +} + +psa_status_t test_transparent_signature_verify_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length ) +{ + ++test_driver_signature_verify_hooks.hits; + + if( test_driver_signature_verify_hooks.forced_status != PSA_SUCCESS ) + return( test_driver_signature_verify_hooks.forced_status ); + + psa_status_t status = PSA_ERROR_NOT_SUPPORTED; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \ + defined(MBEDTLS_SHA256_C) + if( alg != PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ) ) + return( PSA_ERROR_NOT_SUPPORTED ); + mbedtls_ecp_group_id grp_id; + switch( psa_get_key_type( attributes ) ) + { + case PSA_ECC_CURVE_SECP_R1: + switch( psa_get_key_bits( attributes ) ) + { + case 256: + grp_id = MBEDTLS_ECP_DP_SECP256R1; + break; + case 384: + grp_id = MBEDTLS_ECP_DP_SECP384R1; + break; + case 521: + grp_id = MBEDTLS_ECP_DP_SECP521R1; + break; + default: + return( PSA_ERROR_NOT_SUPPORTED ); + } + break; + default: + return( PSA_ERROR_NOT_SUPPORTED ); + } + + /* Beyond this point, the driver is actually doing the work of + * calculating the signature. */ + + status = PSA_ERROR_GENERIC_ERROR; + int ret = 0; + mbedtls_mpi r, s; + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + mbedtls_ecp_keypair ecp; + mbedtls_ecp_keypair_init( &ecp ); + mbedtls_test_rnd_pseudo_info rnd_info; + memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) ); + size_t curve_bytes = PSA_BITS_TO_BYTES( ecp.grp.pbits ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ecp.grp, grp_id ) ); + + /* Code adapted from psa_ecdsa_verify() in psa_crypto.c. */ + if( signature_length < 2 * curve_bytes ) + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, + signature, + curve_bytes ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &s, + signature + curve_bytes, + curve_bytes ) ); + + if( PSA_KEY_TYPE_IS_PUBLIC_KEY( psa_get_key_type( attributes ) ) ) + MBEDTLS_MPI_CHK( mbedtls_ecp_point_read_binary( &ecp.grp, &ecp.Q, + key, key_length ) ); + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ecp.d, key, key_length ) ); + MBEDTLS_MPI_CHK( + mbedtls_ecp_mul( &ecp.grp, &ecp.Q, &ecp.d, &ecp.grp.G, + &mbedtls_test_rnd_pseudo_rand, + &rnd_info ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_ecdsa_verify( &ecp.grp, hash, hash_length, + &ecp.Q, &r, &s ) ); +cleanup: + status = mbedtls_to_psa_error( ret ); + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + mbedtls_ecp_keypair_free( &ecp ); +#else /* defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \ + defined(MBEDTLS_SHA256_C) */ + (void) attributes; + (void) key; + (void) key_length; + (void) alg; + (void) hash; + (void) hash_length; +#endif /* defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \ + defined(MBEDTLS_SHA256_C) */ + + return( status ); +} + +psa_status_t test_opaque_signature_verify_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length ) +{ + (void) attributes; + (void) key; + (void) key_length; + (void) alg; + (void) hash; + (void) hash_length; + (void) signature; + (void) signature_length; + return( PSA_ERROR_NOT_SUPPORTED ); +} + +#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */ diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.data b/tests/suites/test_suite_psa_crypto_driver_wrappers.data new file mode 100644 index 0000000000..74e61723f0 --- /dev/null +++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.data @@ -0,0 +1,41 @@ +sign_hash through transparent driver: calculate in driver +ecdsa_sign:PSA_SUCCESS:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":0:PSA_SUCCESS + +sign_hash through transparent driver: fallback +ecdsa_sign:PSA_ERROR_NOT_SUPPORTED:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":0:PSA_SUCCESS + +sign_hash through transparent driver: error +ecdsa_sign:PSA_ERROR_GENERIC_ERROR:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":0:PSA_ERROR_GENERIC_ERROR + +sign_hash through transparent driver: fake +ecdsa_sign:PSA_SUCCESS:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"000102030405060708090A0B0C0D0E0F":1:PSA_SUCCESS + +verify_hash using private key through transparent driver: calculate in driver +ecdsa_verify:PSA_SUCCESS:0:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_SUCCESS + +verify_hash using private key through transparent driver: fallback +ecdsa_verify:PSA_ERROR_NOT_SUPPORTED:0:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_SUCCESS + +verify_hash using private key through transparent driver: error +ecdsa_verify:PSA_ERROR_GENERIC_ERROR:0:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_ERROR_GENERIC_ERROR + +verify_hash using public key through transparent driver: calculate in driver +ecdsa_verify:PSA_SUCCESS:1:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_SUCCESS + +verify_hash using public key through transparent driver: fallback +ecdsa_verify:PSA_ERROR_NOT_SUPPORTED:1:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_SUCCESS + +verify_hash using public key through transparent driver: error +ecdsa_verify:PSA_ERROR_GENERIC_ERROR:1:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_ERROR_GENERIC_ERROR + +generate_key through transparent driver: fake +generate_key:PSA_SUCCESS:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_SUCCESS + +generate_key through transparent driver: in-driver +generate_key:PSA_SUCCESS:"":PSA_SUCCESS + +generate_key through transparent driver: fallback +generate_key:PSA_ERROR_NOT_SUPPORTED:"":PSA_SUCCESS + +generate_key through transparent driver: error +generate_key:PSA_ERROR_GENERIC_ERROR:"":PSA_ERROR_GENERIC_ERROR diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.function b/tests/suites/test_suite_psa_crypto_driver_wrappers.function new file mode 100644 index 0000000000..917798237e --- /dev/null +++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.function @@ -0,0 +1,185 @@ +/* BEGIN_HEADER */ +#include "test/psa_crypto_helpers.h" + +#include "test/drivers/test_driver.h" +/* END_HEADER */ + +/* BEGIN_DEPENDENCIES + * depends_on:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_PSA_CRYPTO_DRIVERS:PSA_CRYPTO_DRIVER_TEST + * END_DEPENDENCIES + */ + +/* BEGIN_CASE depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C */ +void ecdsa_sign( int force_status_arg, + data_t *key_input, + data_t *data_input, + data_t *expected_output, + int fake_output, + int expected_status_arg ) +{ + psa_status_t force_status = force_status_arg; + psa_status_t expected_status = expected_status_arg; + psa_key_handle_t handle = 0; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t alg = PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ); + uint8_t signature[64]; + size_t signature_length = 0xdeadbeef; + psa_status_t actual_status; + test_driver_signature_sign_hooks = test_driver_signature_hooks_init(); + + PSA_ASSERT( psa_crypto_init( ) ); + psa_set_key_type( &attributes, + PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_CURVE_SECP_R1 ) ); + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH ); + psa_set_key_algorithm( &attributes, alg ); + psa_import_key( &attributes, + key_input->x, key_input->len, + &handle ); + + test_driver_signature_sign_hooks.forced_status = force_status; + if( fake_output == 1 ) + { + test_driver_signature_sign_hooks.forced_output = expected_output->x; + test_driver_signature_sign_hooks.forced_output_length = expected_output->len; + } + + actual_status = psa_sign_hash( handle, alg, + data_input->x, data_input->len, + signature, sizeof( signature ), + &signature_length ); + TEST_EQUAL( actual_status, expected_status ); + if( expected_status == PSA_SUCCESS ) + { + ASSERT_COMPARE( signature, signature_length, + expected_output->x, expected_output->len ); + } + TEST_EQUAL( test_driver_signature_sign_hooks.hits, 1 ); + +exit: + psa_reset_key_attributes( &attributes ); + psa_destroy_key( handle ); + PSA_DONE( ); + test_driver_signature_sign_hooks = test_driver_signature_hooks_init(); +} +/* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C */ +void ecdsa_verify( int force_status_arg, + int register_public_key, + data_t *key_input, + data_t *data_input, + data_t *signature_input, + int expected_status_arg ) +{ + psa_status_t force_status = force_status_arg; + psa_status_t expected_status = expected_status_arg; + psa_key_handle_t handle = 0; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t alg = PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ); + psa_status_t actual_status; + test_driver_signature_verify_hooks = test_driver_signature_hooks_init(); + + PSA_ASSERT( psa_crypto_init( ) ); + if( register_public_key ) + { + psa_set_key_type( &attributes, + PSA_KEY_TYPE_ECC_PUBLIC_KEY( PSA_ECC_CURVE_SECP_R1 ) ); + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_HASH ); + psa_set_key_algorithm( &attributes, alg ); + psa_import_key( &attributes, + key_input->x, key_input->len, + &handle ); + } + else + { + psa_set_key_type( &attributes, + PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_CURVE_SECP_R1 ) ); + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_HASH ); + psa_set_key_algorithm( &attributes, alg ); + psa_import_key( &attributes, + key_input->x, key_input->len, + &handle ); + } + + test_driver_signature_verify_hooks.forced_status = force_status; + + actual_status = psa_verify_hash( handle, alg, + data_input->x, data_input->len, + signature_input->x, signature_input->len ); + TEST_EQUAL( actual_status, expected_status ); + TEST_EQUAL( test_driver_signature_verify_hooks.hits, 1 ); + +exit: + psa_reset_key_attributes( &attributes ); + psa_destroy_key( handle ); + PSA_DONE( ); + test_driver_signature_verify_hooks = test_driver_signature_hooks_init(); +} +/* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +void generate_key( int force_status_arg, + data_t *fake_output, + int expected_status_arg ) +{ + psa_status_t force_status = force_status_arg; + psa_status_t expected_status = expected_status_arg; + psa_key_handle_t handle = 0; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t alg = PSA_ALG_ECDSA( PSA_ALG_SHA_256 ); + const uint8_t *expected_output = NULL; + size_t expected_output_length = 0; + psa_status_t actual_status; + uint8_t actual_output[PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(256)] = {0}; + size_t actual_output_length; + test_driver_keygen_hooks = test_driver_keygen_hooks_init(); + + psa_set_key_type( &attributes, + PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_CURVE_SECP_R1 ) ); + psa_set_key_bits( &attributes, 256 ); + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT ); + psa_set_key_algorithm( &attributes, alg ); + + if( fake_output->len > 0 ) + { + expected_output = test_driver_keygen_hooks.forced_output = fake_output->x; + expected_output_length = test_driver_keygen_hooks.forced_output_length = + fake_output->len; + } + + test_driver_keygen_hooks.hits = 0; + test_driver_keygen_hooks.forced_status = force_status; + + PSA_ASSERT( psa_crypto_init( ) ); + + actual_status = psa_generate_key( &attributes, &handle ); + TEST_EQUAL( test_driver_keygen_hooks.hits, 1 ); + TEST_EQUAL( actual_status, expected_status ); + + if( actual_status == PSA_SUCCESS ) + { + psa_export_key( handle, actual_output, sizeof(actual_output), &actual_output_length ); + + if( fake_output->len > 0 ) + { + ASSERT_COMPARE( actual_output, actual_output_length, + expected_output, expected_output_length ); + } + else + { + size_t zeroes = 0; + for( size_t i = 0; i < sizeof(actual_output); i++ ) + { + if( actual_output[i] == 0) + zeroes++; + } + TEST_ASSERT( zeroes != sizeof(actual_output) ); + } + } +exit: + psa_reset_key_attributes( &attributes ); + psa_destroy_key( handle ); + PSA_DONE( ); + test_driver_keygen_hooks = test_driver_keygen_hooks_init(); +} +/* END_CASE */ diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj index 578289f17f..9d79298397 100644 --- a/visualc/VS2010/mbedTLS.vcxproj +++ b/visualc/VS2010/mbedTLS.vcxproj @@ -238,8 +238,12 @@ + + + + @@ -307,6 +311,7 @@ +