Add and splice in signature verification through driver

Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
diff --git a/tests/include/drivers/signature.h b/tests/include/drivers/signature.h
index 1607ba5..232ed41 100644
--- a/tests/include/drivers/signature.h
+++ b/tests/include/drivers/signature.h
@@ -37,6 +37,9 @@
 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 @@
     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 983e121..a3f67be 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -1657,7 +1657,7 @@
 }
 
 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 0f006c7..32ebbfd 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 <string.h>
 
 /* If non-null, on success, copy this to the output. */
@@ -43,6 +45,9 @@
 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 @@
     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 fd20b18..2d2c5c4 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 @@
 
 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 8c6338c..a954446 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 @@
     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 @@
     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 */