Skip to content

Commit 494624d

Browse files
authored
Merge pull request #18 from gilles-peskine-arm/psa-hash_clone
New function psa_hash_clone
2 parents 9c0c79e + eb35d78 commit 494624d

File tree

5 files changed

+189
-1
lines changed

5 files changed

+189
-1
lines changed

include/psa/crypto.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,33 @@ psa_status_t psa_hash_verify(psa_hash_operation_t *operation,
902902
*/
903903
psa_status_t psa_hash_abort(psa_hash_operation_t *operation);
904904

905+
/** Clone a hash operation.
906+
*
907+
* This function copies the state of an ongoing hash operation to
908+
* a new operation object. In other words, this function is equivalent
909+
* to calling psa_hash_setup() on \p target_operation with the same
910+
* algorithm that \p source_operation was set up for, then
911+
* psa_hash_update() on \p target_operation with the same input that
912+
* that was passed to \p source_operation. After this function returns, the
913+
* two objects are independent, i.e. subsequent calls involving one of
914+
* the objects do not affect the other object.
915+
*
916+
* \param[in] source_operation The active hash operation to clone.
917+
* \param[in,out] target_operation The operation object to set up.
918+
* It must be initialized but not active.
919+
*
920+
* \retval #PSA_SUCCESS
921+
* \retval #PSA_ERROR_BAD_STATE
922+
* \p source_operation is not an active hash operation.
923+
* \retval #PSA_ERROR_BAD_STATE
924+
* \p target_operation is active.
925+
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
926+
* \retval #PSA_ERROR_HARDWARE_FAILURE
927+
* \retval #PSA_ERROR_TAMPERING_DETECTED
928+
*/
929+
psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation,
930+
psa_hash_operation_t *target_operation);
931+
905932
/**@}*/
906933

907934
/** \defgroup MAC Message authentication codes

library/psa_crypto.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,6 +1421,67 @@ psa_status_t psa_hash_verify( psa_hash_operation_t *operation,
14211421
return( PSA_SUCCESS );
14221422
}
14231423

1424+
psa_status_t psa_hash_clone( const psa_hash_operation_t *source_operation,
1425+
psa_hash_operation_t *target_operation )
1426+
{
1427+
if( target_operation->alg != 0 )
1428+
return( PSA_ERROR_BAD_STATE );
1429+
1430+
switch( source_operation->alg )
1431+
{
1432+
case 0:
1433+
return( PSA_ERROR_BAD_STATE );
1434+
#if defined(MBEDTLS_MD2_C)
1435+
case PSA_ALG_MD2:
1436+
mbedtls_md2_clone( &target_operation->ctx.md2,
1437+
&source_operation->ctx.md2 );
1438+
break;
1439+
#endif
1440+
#if defined(MBEDTLS_MD4_C)
1441+
case PSA_ALG_MD4:
1442+
mbedtls_md4_clone( &target_operation->ctx.md4,
1443+
&source_operation->ctx.md4 );
1444+
break;
1445+
#endif
1446+
#if defined(MBEDTLS_MD5_C)
1447+
case PSA_ALG_MD5:
1448+
mbedtls_md5_clone( &target_operation->ctx.md5,
1449+
&source_operation->ctx.md5 );
1450+
break;
1451+
#endif
1452+
#if defined(MBEDTLS_RIPEMD160_C)
1453+
case PSA_ALG_RIPEMD160:
1454+
mbedtls_ripemd160_clone( &target_operation->ctx.ripemd160,
1455+
&source_operation->ctx.ripemd160 );
1456+
break;
1457+
#endif
1458+
#if defined(MBEDTLS_SHA1_C)
1459+
case PSA_ALG_SHA_1:
1460+
mbedtls_sha1_clone( &target_operation->ctx.sha1,
1461+
&source_operation->ctx.sha1 );
1462+
break;
1463+
#endif
1464+
#if defined(MBEDTLS_SHA256_C)
1465+
case PSA_ALG_SHA_224:
1466+
case PSA_ALG_SHA_256:
1467+
mbedtls_sha256_clone( &target_operation->ctx.sha256,
1468+
&source_operation->ctx.sha256 );
1469+
break;
1470+
#endif
1471+
#if defined(MBEDTLS_SHA512_C)
1472+
case PSA_ALG_SHA_384:
1473+
case PSA_ALG_SHA_512:
1474+
mbedtls_sha512_clone( &target_operation->ctx.sha512,
1475+
&source_operation->ctx.sha512 );
1476+
break;
1477+
#endif
1478+
default:
1479+
return( PSA_ERROR_NOT_SUPPORTED );
1480+
}
1481+
1482+
target_operation->alg = source_operation->alg;
1483+
return( PSA_SUCCESS );
1484+
}
14241485

14251486

14261487
/****************************************************************/

tests/suites/test_suite_psa_crypto.data

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,12 @@ hash_verify_bad_args:
527527
PSA hash finish: bad arguments
528528
hash_finish_bad_args:
529529

530+
PSA hash clone: source state
531+
hash_clone_source_state:
532+
533+
PSA hash clone: target state
534+
hash_clone_target_state:
535+
530536
MAC operation object initializers zero properly
531537
mac_operation_init:
532538

tests/suites/test_suite_psa_crypto.function

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1897,6 +1897,92 @@ exit:
18971897
}
18981898
/* END_CASE */
18991899

1900+
/* BEGIN_CASE depends_on:MBEDTLS_SHA256_C */
1901+
void hash_clone_source_state( )
1902+
{
1903+
psa_algorithm_t alg = PSA_ALG_SHA_256;
1904+
unsigned char hash[PSA_HASH_MAX_SIZE];
1905+
psa_hash_operation_t op_source = PSA_HASH_OPERATION_INIT;
1906+
psa_hash_operation_t op_init = PSA_HASH_OPERATION_INIT;
1907+
psa_hash_operation_t op_setup = PSA_HASH_OPERATION_INIT;
1908+
psa_hash_operation_t op_finished = PSA_HASH_OPERATION_INIT;
1909+
psa_hash_operation_t op_aborted = PSA_HASH_OPERATION_INIT;
1910+
size_t hash_len;
1911+
1912+
PSA_ASSERT( psa_crypto_init( ) );
1913+
PSA_ASSERT( psa_hash_setup( &op_source, alg ) );
1914+
1915+
PSA_ASSERT( psa_hash_setup( &op_setup, alg ) );
1916+
PSA_ASSERT( psa_hash_setup( &op_finished, alg ) );
1917+
PSA_ASSERT( psa_hash_finish( &op_finished,
1918+
hash, sizeof( hash ), &hash_len ) );
1919+
PSA_ASSERT( psa_hash_setup( &op_aborted, alg ) );
1920+
PSA_ASSERT( psa_hash_abort( &op_aborted ) );
1921+
1922+
TEST_EQUAL( psa_hash_clone( &op_source, &op_setup ),
1923+
PSA_ERROR_BAD_STATE );
1924+
1925+
PSA_ASSERT( psa_hash_clone( &op_source, &op_init ) );
1926+
PSA_ASSERT( psa_hash_finish( &op_init,
1927+
hash, sizeof( hash ), &hash_len ) );
1928+
PSA_ASSERT( psa_hash_clone( &op_source, &op_finished ) );
1929+
PSA_ASSERT( psa_hash_finish( &op_finished,
1930+
hash, sizeof( hash ), &hash_len ) );
1931+
PSA_ASSERT( psa_hash_clone( &op_source, &op_aborted ) );
1932+
PSA_ASSERT( psa_hash_finish( &op_aborted,
1933+
hash, sizeof( hash ), &hash_len ) );
1934+
1935+
exit:
1936+
psa_hash_abort( &op_source );
1937+
psa_hash_abort( &op_init );
1938+
psa_hash_abort( &op_setup );
1939+
psa_hash_abort( &op_finished );
1940+
psa_hash_abort( &op_aborted );
1941+
mbedtls_psa_crypto_free( );
1942+
}
1943+
/* END_CASE */
1944+
1945+
/* BEGIN_CASE depends_on:MBEDTLS_SHA256_C */
1946+
void hash_clone_target_state( )
1947+
{
1948+
psa_algorithm_t alg = PSA_ALG_SHA_256;
1949+
unsigned char hash[PSA_HASH_MAX_SIZE];
1950+
psa_hash_operation_t op_init = PSA_HASH_OPERATION_INIT;
1951+
psa_hash_operation_t op_setup = PSA_HASH_OPERATION_INIT;
1952+
psa_hash_operation_t op_finished = PSA_HASH_OPERATION_INIT;
1953+
psa_hash_operation_t op_aborted = PSA_HASH_OPERATION_INIT;
1954+
psa_hash_operation_t op_target = PSA_HASH_OPERATION_INIT;
1955+
size_t hash_len;
1956+
1957+
PSA_ASSERT( psa_crypto_init( ) );
1958+
1959+
PSA_ASSERT( psa_hash_setup( &op_setup, alg ) );
1960+
PSA_ASSERT( psa_hash_setup( &op_finished, alg ) );
1961+
PSA_ASSERT( psa_hash_finish( &op_finished,
1962+
hash, sizeof( hash ), &hash_len ) );
1963+
PSA_ASSERT( psa_hash_setup( &op_aborted, alg ) );
1964+
PSA_ASSERT( psa_hash_abort( &op_aborted ) );
1965+
1966+
PSA_ASSERT( psa_hash_clone( &op_setup, &op_target ) );
1967+
PSA_ASSERT( psa_hash_finish( &op_target,
1968+
hash, sizeof( hash ), &hash_len ) );
1969+
1970+
TEST_EQUAL( psa_hash_clone( &op_init, &op_target ), PSA_ERROR_BAD_STATE );
1971+
TEST_EQUAL( psa_hash_clone( &op_finished, &op_target ),
1972+
PSA_ERROR_BAD_STATE );
1973+
TEST_EQUAL( psa_hash_clone( &op_aborted, &op_target ),
1974+
PSA_ERROR_BAD_STATE );
1975+
1976+
exit:
1977+
psa_hash_abort( &op_target );
1978+
psa_hash_abort( &op_init );
1979+
psa_hash_abort( &op_setup );
1980+
psa_hash_abort( &op_finished );
1981+
psa_hash_abort( &op_aborted );
1982+
mbedtls_psa_crypto_free( );
1983+
}
1984+
/* END_CASE */
1985+
19001986
/* BEGIN_CASE */
19011987
void mac_operation_init( )
19021988
{

tests/suites/test_suite_psa_crypto_hash.function

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ void hash_multi_part( int alg_arg, data_t *input, data_t *expected_hash )
6767
unsigned char actual_hash[PSA_HASH_MAX_SIZE];
6868
size_t actual_hash_length;
6969
psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
70+
psa_hash_operation_t operation2 = PSA_HASH_OPERATION_INIT;
7071
uint32_t len = 0;
7172

7273
PSA_ASSERT( psa_crypto_init( ) );
@@ -78,16 +79,23 @@ void hash_multi_part( int alg_arg, data_t *input, data_t *expected_hash )
7879

7980
PSA_ASSERT( psa_hash_update( &operation,
8081
input->x, len ) );
82+
PSA_ASSERT( psa_hash_clone( &operation, &operation2 ) );
8183
PSA_ASSERT( psa_hash_update( &operation,
8284
input->x + len, input->len - len ) );
85+
PSA_ASSERT( psa_hash_update( &operation2,
86+
input->x + len, input->len - len ) );
8387

8488
PSA_ASSERT( psa_hash_finish( &operation,
8589
actual_hash, sizeof( actual_hash ),
8690
&actual_hash_length ) );
87-
8891
ASSERT_COMPARE( expected_hash->x, expected_hash->len,
8992
actual_hash, actual_hash_length );
9093

94+
PSA_ASSERT( psa_hash_finish( &operation2,
95+
actual_hash, sizeof( actual_hash ),
96+
&actual_hash_length ) );
97+
ASSERT_COMPARE( expected_hash->x, expected_hash->len,
98+
actual_hash, actual_hash_length );
9199
} while( len++ != input->len );
92100

93101
exit:

0 commit comments

Comments
 (0)