From 0a749c8fa33bf7425df47109bb3156644960949d Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 28 Nov 2019 19:33:58 +0100 Subject: [PATCH] Implement and test psa_hash_compute, psa_hash_compare --- library/psa_crypto.c | 52 +++++++++++++ tests/suites/test_suite_psa_crypto.data | 52 +++++++++++++ tests/suites/test_suite_psa_crypto.function | 83 +++++++++++++++++++++ 3 files changed, 187 insertions(+) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 154806a3fa..98166684e7 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -2351,6 +2351,58 @@ psa_status_t psa_hash_verify( psa_hash_operation_t *operation, return( PSA_SUCCESS ); } +psa_status_t psa_hash_compute( psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *hash, size_t hash_size, + size_t *hash_length ) +{ + psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + *hash_length = hash_size; + status = psa_hash_setup( &operation, alg ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_hash_update( &operation, input, input_length ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_hash_finish( &operation, hash, hash_size, hash_length ); + if( status != PSA_SUCCESS ) + goto exit; + +exit: + if( status == PSA_SUCCESS ) + status = psa_hash_abort( &operation ); + else + psa_hash_abort( &operation ); + return( status ); +} + +psa_status_t psa_hash_compare( psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + const uint8_t *hash, size_t hash_length ) +{ + psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + status = psa_hash_setup( &operation, alg ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_hash_update( &operation, input, input_length ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_hash_verify( &operation, hash, hash_length ); + if( status != PSA_SUCCESS ) + goto exit; + +exit: + if( status == PSA_SUCCESS ) + status = psa_hash_abort( &operation ); + else + psa_hash_abort( &operation ); + return( status ); +} + psa_status_t psa_hash_clone( const psa_hash_operation_t *source_operation, psa_hash_operation_t *target_operation ) { diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 26dca18a4c..4cdba31a6e 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -774,6 +774,58 @@ hash_verify_bad_args: PSA hash finish: bad arguments hash_finish_bad_args: +PSA hash compute: bad algorithm (unknown hash) +depends_on:MBEDTLS_SHA256_C +hash_compute_fail:PSA_ALG_CATEGORY_HASH:"":32:PSA_ERROR_NOT_SUPPORTED + +PSA hash compute: bad algorithm (wildcard) +depends_on:MBEDTLS_SHA256_C +hash_compute_fail:PSA_ALG_ANY_HASH:"":32:PSA_ERROR_NOT_SUPPORTED + +PSA hash compute: bad algorithm (not a hash) +depends_on:MBEDTLS_SHA256_C +hash_compute_fail:PSA_ALG_HMAC(PSA_ALG_SHA_256):"":32:PSA_ERROR_INVALID_ARGUMENT + +PSA hash compute: output buffer too small +depends_on:MBEDTLS_SHA256_C +hash_compute_fail:PSA_ALG_SHA_256:"":31:PSA_ERROR_BUFFER_TOO_SMALL + +PSA hash compute: good, SHA-1 +depends_on:MBEDTLS_SHA1_C +hash_compute_compare:PSA_ALG_SHA_1:"42749e":"a444319e9b6cc1e8464c511ec0969c37d6bb2619" + +PSA hash compute: good, SHA-224 +depends_on:MBEDTLS_SHA256_C +hash_compute_compare:PSA_ALG_SHA_224:"50efd0":"b5a9820413c2bf8211fbbf5df1337043b32fa4eafaf61a0c8e9ccede" + +PSA hash compute: good, SHA-256 +depends_on:MBEDTLS_SHA256_C +hash_compute_compare:PSA_ALG_SHA_256:"b0bd69":"4096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803" + +PSA hash compute: good, SHA-384 +depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384 +hash_compute_compare:PSA_ALG_SHA_384:"31f5ca":"78d54b943421fdf7ba90a7fb9637c2073aa480454bd841d39ff72f4511fc21fb67797b652c0c823229342873d3bef955" + +PSA hash compute: good, SHA-512 +depends_on:MBEDTLS_SHA512_C +hash_compute_compare:PSA_ALG_SHA_512:"de4c90":"33ce98281045a5c4c9df0363d8196f1d7dfcd5ee46ac89776fd8a4344c12f123a66788af5bd41ceff1941aa5637654b4064c88c14e00465ab79a2fc6c97e1014" + +PSA hash compute: good, MD2 +depends_on:MBEDTLS_MD2_C +hash_compute_compare:PSA_ALG_MD2:"616263":"da853b0d3f88d99b30283a69e6ded6bb" + +PSA hash compute: good, MD4 +depends_on:MBEDTLS_MD4_C +hash_compute_compare:PSA_ALG_MD4:"616263":"a448017aaf21d8525fc10ae87aa6729d" + +PSA hash compute: good, MD5 +depends_on:MBEDTLS_MD5_C +hash_compute_compare:PSA_ALG_MD5:"616263":"900150983cd24fb0d6963f7d28e17f72" + +PSA hash compute: good, RIPEMD160 +depends_on:MBEDTLS_RIPEMD160_C +hash_compute_compare:PSA_ALG_RIPEMD160:"616263":"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc" + PSA hash clone: source state hash_clone_source_state: diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index ba7c192b8b..c9c45b7e14 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -2430,6 +2430,89 @@ exit: } /* END_CASE */ +/* BEGIN_CASE */ +void hash_compute_fail( int alg_arg, data_t *input, + int output_size_arg, int expected_status_arg ) +{ + psa_algorithm_t alg = alg_arg; + uint8_t *output = NULL; + size_t output_size = output_size_arg; + size_t output_length = INVALID_EXPORT_LENGTH; + psa_status_t expected_status = expected_status_arg; + psa_status_t status; + + ASSERT_ALLOC( output, output_size ); + + PSA_ASSERT( psa_crypto_init( ) ); + + status = psa_hash_compute( alg, input->x, input->len, + output, output_size, &output_length ); + TEST_EQUAL( status, expected_status ); + TEST_ASSERT( output_length <= output_size ); + +exit: + mbedtls_free( output ); + PSA_DONE( ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void hash_compute_compare( int alg_arg, data_t *input, + data_t *expected_output ) +{ + psa_algorithm_t alg = alg_arg; + uint8_t output[PSA_HASH_MAX_SIZE + 1]; + size_t output_length = INVALID_EXPORT_LENGTH; + size_t i; + + PSA_ASSERT( psa_crypto_init( ) ); + + /* Compute with tight buffer */ + PSA_ASSERT( psa_hash_compute( alg, input->x, input->len, + output, PSA_HASH_SIZE( alg ), + &output_length ) ); + TEST_EQUAL( output_length, PSA_HASH_SIZE( alg ) ); + ASSERT_COMPARE( output, output_length, + expected_output->x, expected_output->len ); + + /* Compute with larger buffer */ + PSA_ASSERT( psa_hash_compute( alg, input->x, input->len, + output, sizeof( output ), + &output_length ) ); + TEST_EQUAL( output_length, PSA_HASH_SIZE( alg ) ); + ASSERT_COMPARE( output, output_length, + expected_output->x, expected_output->len ); + + /* Compare with correct hash */ + PSA_ASSERT( psa_hash_compare( alg, input->x, input->len, + output, output_length ) ); + + /* Compare with trailing garbage */ + TEST_EQUAL( psa_hash_compare( alg, input->x, input->len, + output, output_length + 1 ), + PSA_ERROR_INVALID_SIGNATURE ); + + /* Compare with truncated hash */ + TEST_EQUAL( psa_hash_compare( alg, input->x, input->len, + output, output_length - 1 ), + PSA_ERROR_INVALID_SIGNATURE ); + + /* Compare with corrupted value */ + for( i = 0; i < output_length; i++ ) + { + test_set_step( i ); + output[i] ^= 1; + TEST_EQUAL( psa_hash_compare( alg, input->x, input->len, + output, output_length ), + PSA_ERROR_INVALID_SIGNATURE ); + output[i] ^= 1; + } + +exit: + PSA_DONE( ); +} +/* END_CASE */ + /* BEGIN_CASE */ void hash_bad_order( ) {