Add and splice in signature verification through driver

Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
This commit is contained in:
Steven Cooreman 2020-07-17 19:46:15 +02:00
parent 7a2505788c
commit 55ae2176ab
8 changed files with 352 additions and 19 deletions

View file

@ -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,
/* Try any of the available accelerators first */
status = psa_driver_wrapper_verify_hash( slot,
alg,
hash, hash_length,
signature, signature_length ) );
}
else
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
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 ) )
{

View file

@ -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. */

View file

@ -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. */

View file

@ -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 */

View file

@ -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

View file

@ -34,6 +34,8 @@
#include "mbedtls/md.h"
#include "mbedtls/ecdsa.h"
#include "test/random.h"
#include <string.h>
/* 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 */

View file

@ -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

View file

@ -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 */