diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 460b9df6c..edef287c1 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -3754,29 +3754,21 @@ 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 ) + return status; + #if defined(MBEDTLS_RSA_C) if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) { diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c index 06f33699d..09a7ccd32 100644 --- a/library/psa_crypto_driver_wrappers.c +++ b/library/psa_crypto_driver_wrappers.c @@ -135,4 +135,101 @@ psa_status_t psa_driver_wrapper_sign_hash( psa_key_slot_t *slot, #endif /* MBEDTLS_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(MBEDTLS_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_INVALID_ARGUMENT; + } + return( drv->asymmetric->p_verify( drv_context, + slot->data.se.slot_number, + alg, + hash, hash_length, + signature, signature_length ) ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + /* Then try accelerator API */ +#if defined(MBEDTLS_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(MBEDTLS_TEST_HOOKS) + 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 /* MBEDTLS_TEST_HOOKS */ + /* Fell through, meaning no accelerator supports this operation */ + return PSA_ERROR_NOT_SUPPORTED; + /* Add cases for opaque driver here */ +#if defined(MBEDTLS_TEST_HOOKS) + case MBEDTLS_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 /* MBEDTLS_TEST_HOOKS */ + default: + /* Key is declared with a lifetime not known to us */ + return status; + } +#else /* MBEDTLS_PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + return PSA_ERROR_NOT_SUPPORTED; +#endif /* MBEDTLS_PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ +#else /* MBEDTLS_PSA_CRYPTO_DRIVER_PRESENT */ + (void)slot; + (void)alg; + (void)hash; + (void)hash_length; + (void)signature; + (void)signature_length; + + return PSA_ERROR_NOT_SUPPORTED; +#endif /* MBEDTLS_PSA_CRYPTO_DRIVER_PRESENT */ +} + +psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attributes, + psa_key_slot_t *slot ) +{ + (void) attributes; + (void) slot; + + return PSA_ERROR_NOT_SUPPORTED; +} + /* End of automatically generated file. */ diff --git a/library/psa_crypto_driver_wrappers.h b/library/psa_crypto_driver_wrappers.h index 8fbf034c6..6ab2d9019 100644 --- a/library/psa_crypto_driver_wrappers.h +++ b/library/psa_crypto_driver_wrappers.h @@ -35,6 +35,16 @@ psa_status_t psa_driver_wrapper_sign_hash( psa_key_slot_t *slot, 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/tests/include/drivers/signature.h b/tests/include/drivers/signature.h index 1607ba512..232ed4147 100644 --- a/tests/include/drivers/signature.h +++ b/tests/include/drivers/signature.h @@ -37,6 +37,9 @@ extern size_t test_driver_forced_output_length; extern psa_status_t test_transparent_signature_sign_hash_status; extern unsigned long test_transparent_signature_sign_hash_hit; +extern psa_status_t test_transparent_signature_verify_hash_status; +extern unsigned long test_transparent_signature_verify_hash_hit; + psa_status_t test_transparent_signature_sign_hash( const psa_key_attributes_t *attributes, const uint8_t *key, size_t key_length, @@ -51,5 +54,19 @@ psa_status_t test_opaque_signature_sign_hash( 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 /* MBEDTLS_TEST_HOOKS */ #endif /* MBEDTLS_PSA_CRYPTO_TEST_DRIVERS_SIGNATURE_H */ diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index 983e12124..a3f67bef8 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -1657,7 +1657,7 @@ component_test_se_default () { } component_test_psa_crypto_drivers () { - msg "build: MBEDTLS_PSA_CRYPTO_DRIVERS, signature" + msg "build: MBEDTLS_PSA_CRYPTO_DRIVERS w/ driver hooks" scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS scripts/config.py set MBEDTLS_TEST_HOOKS # Need to include the test driver header path in order to build diff --git a/tests/src/drivers/signature.c b/tests/src/drivers/signature.c index 0f006c70a..32ebbfdff 100644 --- a/tests/src/drivers/signature.c +++ b/tests/src/drivers/signature.c @@ -34,6 +34,8 @@ #include "mbedtls/md.h" #include "mbedtls/ecdsa.h" +#include "test/random.h" + #include /* If non-null, on success, copy this to the output. */ @@ -43,6 +45,9 @@ size_t test_driver_forced_output_length = 0; psa_status_t test_transparent_signature_sign_hash_status = PSA_ERROR_NOT_SUPPORTED; unsigned long test_transparent_signature_sign_hash_hit = 0; +psa_status_t test_transparent_signature_verify_hash_status = PSA_ERROR_NOT_SUPPORTED; +unsigned long test_transparent_signature_verify_hash_hit = 0; + psa_status_t test_transparent_signature_sign_hash( const psa_key_attributes_t *attributes, const uint8_t *key, size_t key_length, @@ -168,4 +173,129 @@ psa_status_t test_opaque_signature_sign_hash( 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_transparent_signature_verify_hash_hit; + + if( test_transparent_signature_verify_hash_status != PSA_SUCCESS ) + return( test_transparent_signature_verify_hash_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: + /* There's no easy way to translate the error code except through a + * library function that's not exported. Use a debugger. */ + if( ret == 0 ) + status = PSA_SUCCESS; + 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 && MBEDTLS_TEST_HOOKS */ diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.data b/tests/suites/test_suite_psa_crypto_driver_wrappers.data index fd20b1872..2d2c5c4b4 100644 --- a/tests/suites/test_suite_psa_crypto_driver_wrappers.data +++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.data @@ -9,3 +9,21 @@ ecdsa_sign:PSA_ERROR_GENERIC_ERROR:0:PSA_ERROR_GENERIC_ERROR sign_hash through transparent driver: fake ecdsa_sign:PSA_SUCCESS:1:PSA_SUCCESS + +verify_hash using private key through transparent driver: calculate in driver +ecdsa_verify:PSA_SUCCESS:0:PSA_SUCCESS + +verify_hash using private key through transparent driver: fallback +ecdsa_verify:PSA_ERROR_NOT_SUPPORTED:0:PSA_SUCCESS + +verify_hash using private key through transparent driver: error +ecdsa_verify:PSA_ERROR_GENERIC_ERROR:0:PSA_ERROR_GENERIC_ERROR + +verify_hash using public key through transparent driver: calculate in driver +ecdsa_verify:PSA_SUCCESS:1:PSA_SUCCESS + +verify_hash using public key through transparent driver: fallback +ecdsa_verify:PSA_ERROR_NOT_SUPPORTED:1:PSA_SUCCESS + +verify_hash through transparent driver: error +ecdsa_verify:PSA_ERROR_GENERIC_ERROR:1: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 index 8c6338c0c..a954446ed 100644 --- a/tests/suites/test_suite_psa_crypto_driver_wrappers.function +++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.function @@ -25,6 +25,17 @@ uint8_t test_signature_hash_32_with_secp256r1[64] = { 0x3c, 0x24, 0x12, 0x53, 0x4b, 0xb4, 0xa1, 0x9b, 0x3a, 0x78, 0x11, 0x74, 0x2f, 0x49, 0xf5, 0x0f, }; +uint8_t test_secp256r1_public_key_data[65] = { + 0x04, + 0xde, 0xa5, 0xe4, 0x5d, 0x0e, 0xa3, 0x7f, 0xc5, + 0x66, 0x23, 0x2a, 0x50, 0x8f, 0x4a, 0xd2, 0x0e, + 0xa1, 0x3d, 0x47, 0xe4, 0xbf, 0x5f, 0xa4, 0xd5, + 0x4a, 0x57, 0xa0, 0xba, 0x01, 0x20, 0x42, 0x08, + 0x70, 0x97, 0x49, 0x6e, 0xfc, 0x58, 0x3f, 0xed, + 0x8b, 0x24, 0xa5, 0xb9, 0xbe, 0x9a, 0x51, 0xde, + 0x06, 0x3f, 0x5a, 0x00, 0xa8, 0xb6, 0x98, 0xa1, + 0x6f, 0xd7, 0xf2, 0x9b, 0x54, 0x85, 0xf3, 0x20 +}; uint8_t test_fake_output[] = "INJECTED OUTPUT"; @@ -102,3 +113,61 @@ exit: test_driver_forced_output_length = 0; } /* 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, + 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 ); + const uint8_t *expected_output; + size_t expected_output_length; + psa_status_t actual_status; + + 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, + test_secp256r1_public_key_data, sizeof( test_secp256r1_public_key_data ), + &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, + test_secp256r1_key_data, sizeof( test_secp256r1_key_data ), + &handle ); + } + + test_transparent_signature_verify_hash_hit = 0; + test_transparent_signature_verify_hash_status = force_status; + + expected_output = test_signature_hash_32_with_secp256r1; + expected_output_length = sizeof( test_signature_hash_32_with_secp256r1 ); + + actual_status = psa_verify_hash( handle, alg, + test_hash_32, sizeof( test_hash_32 ), + expected_output, expected_output_length ); + TEST_EQUAL( actual_status, expected_status ); + TEST_EQUAL( test_transparent_signature_verify_hash_hit, 1 ); + +exit: + psa_reset_key_attributes( &attributes ); + psa_destroy_key( handle ); + PSA_DONE( ); + test_transparent_signature_sign_hash_status = PSA_ERROR_NOT_SUPPORTED; + test_driver_forced_output = NULL; + test_driver_forced_output_length = 0; +} +/* END_CASE */