New function psa_hash_clone
Clone a hash operation.
Test good cases as part as multipart tests. Add new test functions for
the state machine.
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index 683feb8..e639906 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -921,6 +921,24 @@
*/
psa_status_t psa_hash_abort(psa_hash_operation_t *operation);
+/** Clone a hash operation.
+ *
+ * \param[in] source_operation The active hash operation to clone.
+ * \param[in,out] target_operation The operation object to set up.
+ * It must be initialized but not active.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_BAD_STATE
+ * \p source_operation is not an active hash operation.
+ * \retval #PSA_ERROR_BAD_STATE
+ * \p source_operation is active.
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation,
+ psa_hash_operation_t *target_operation);
+
/**@}*/
/** \defgroup MAC Message authentication codes
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index fd76b27..1dda49b 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -1421,6 +1421,67 @@
return( PSA_SUCCESS );
}
+psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation,
+ psa_hash_operation_t *target_operation)
+{
+ if( target_operation->alg != 0 )
+ return( PSA_ERROR_BAD_STATE );
+
+ switch( source_operation->alg )
+ {
+ case 0:
+ return( PSA_ERROR_BAD_STATE );
+#if defined(MBEDTLS_MD2_C)
+ case PSA_ALG_MD2:
+ mbedtls_md2_clone( &target_operation->ctx.md2,
+ &source_operation->ctx.md2 );
+ break;
+#endif
+#if defined(MBEDTLS_MD4_C)
+ case PSA_ALG_MD4:
+ mbedtls_md4_clone( &target_operation->ctx.md4,
+ &source_operation->ctx.md4 );
+ break;
+#endif
+#if defined(MBEDTLS_MD5_C)
+ case PSA_ALG_MD5:
+ mbedtls_md5_clone( &target_operation->ctx.md5,
+ &source_operation->ctx.md5 );
+ break;
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+ case PSA_ALG_RIPEMD160:
+ mbedtls_ripemd160_clone( &target_operation->ctx.ripemd160,
+ &source_operation->ctx.ripemd160 );
+ break;
+#endif
+#if defined(MBEDTLS_SHA1_C)
+ case PSA_ALG_SHA_1:
+ mbedtls_sha1_clone( &target_operation->ctx.sha1,
+ &source_operation->ctx.sha1 );
+ break;
+#endif
+#if defined(MBEDTLS_SHA256_C)
+ case PSA_ALG_SHA_224:
+ case PSA_ALG_SHA_256:
+ mbedtls_sha256_clone( &target_operation->ctx.sha256,
+ &source_operation->ctx.sha256 );
+ break;
+#endif
+#if defined(MBEDTLS_SHA512_C)
+ case PSA_ALG_SHA_384:
+ case PSA_ALG_SHA_512:
+ mbedtls_sha512_clone( &target_operation->ctx.sha512,
+ &source_operation->ctx.sha512 );
+ break;
+#endif
+ default:
+ return( PSA_ERROR_NOT_SUPPORTED );
+ }
+
+ target_operation->alg = source_operation->alg;
+ return( PSA_SUCCESS );
+}
/****************************************************************/
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index aa0a890..4df20fd 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -527,6 +527,12 @@
PSA hash finish: bad arguments
hash_finish_bad_args:
+PSA hash clone: source state
+hash_clone_source_state:
+
+PSA hash clone: target state
+hash_clone_target_state:
+
MAC operation object initializers zero properly
mac_operation_init:
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index 6916bf4..3865d90 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -1924,6 +1924,92 @@
}
/* END_CASE */
+/* BEGIN_CASE depends_on:MBEDTLS_SHA256_C */
+void hash_clone_source_state( )
+{
+ psa_algorithm_t alg = PSA_ALG_SHA_256;
+ unsigned char hash[PSA_HASH_MAX_SIZE];
+ psa_hash_operation_t op_source = PSA_HASH_OPERATION_INIT;
+ psa_hash_operation_t op_init = PSA_HASH_OPERATION_INIT;
+ psa_hash_operation_t op_setup = PSA_HASH_OPERATION_INIT;
+ psa_hash_operation_t op_finished = PSA_HASH_OPERATION_INIT;
+ psa_hash_operation_t op_aborted = PSA_HASH_OPERATION_INIT;
+ size_t hash_len;
+
+ PSA_ASSERT( psa_crypto_init( ) );
+ PSA_ASSERT( psa_hash_setup( &op_source, alg ) );
+
+ PSA_ASSERT( psa_hash_setup( &op_setup, alg ) );
+ PSA_ASSERT( psa_hash_setup( &op_finished, alg ) );
+ PSA_ASSERT( psa_hash_finish( &op_finished,
+ hash, sizeof( hash ), &hash_len ) );
+ PSA_ASSERT( psa_hash_setup( &op_aborted, alg ) );
+ PSA_ASSERT( psa_hash_abort( &op_aborted ) );
+
+ TEST_EQUAL( psa_hash_clone( &op_source, &op_setup ),
+ PSA_ERROR_BAD_STATE );
+
+ PSA_ASSERT( psa_hash_clone( &op_source, &op_init ) );
+ PSA_ASSERT( psa_hash_finish( &op_init,
+ hash, sizeof( hash ), &hash_len ) );
+ PSA_ASSERT( psa_hash_clone( &op_source, &op_finished ) );
+ PSA_ASSERT( psa_hash_finish( &op_finished,
+ hash, sizeof( hash ), &hash_len ) );
+ PSA_ASSERT( psa_hash_clone( &op_source, &op_aborted ) );
+ PSA_ASSERT( psa_hash_finish( &op_aborted,
+ hash, sizeof( hash ), &hash_len ) );
+
+exit:
+ psa_hash_abort( &op_source );
+ psa_hash_abort( &op_init );
+ psa_hash_abort( &op_setup );
+ psa_hash_abort( &op_finished );
+ psa_hash_abort( &op_aborted );
+ mbedtls_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SHA256_C */
+void hash_clone_target_state( )
+{
+ psa_algorithm_t alg = PSA_ALG_SHA_256;
+ unsigned char hash[PSA_HASH_MAX_SIZE];
+ psa_hash_operation_t op_init = PSA_HASH_OPERATION_INIT;
+ psa_hash_operation_t op_setup = PSA_HASH_OPERATION_INIT;
+ psa_hash_operation_t op_finished = PSA_HASH_OPERATION_INIT;
+ psa_hash_operation_t op_aborted = PSA_HASH_OPERATION_INIT;
+ psa_hash_operation_t op_target = PSA_HASH_OPERATION_INIT;
+ size_t hash_len;
+
+ PSA_ASSERT( psa_crypto_init( ) );
+
+ PSA_ASSERT( psa_hash_setup( &op_setup, alg ) );
+ PSA_ASSERT( psa_hash_setup( &op_finished, alg ) );
+ PSA_ASSERT( psa_hash_finish( &op_finished,
+ hash, sizeof( hash ), &hash_len ) );
+ PSA_ASSERT( psa_hash_setup( &op_aborted, alg ) );
+ PSA_ASSERT( psa_hash_abort( &op_aborted ) );
+
+ PSA_ASSERT( psa_hash_clone( &op_setup, &op_target ) );
+ PSA_ASSERT( psa_hash_finish( &op_target,
+ hash, sizeof( hash ), &hash_len ) );
+
+ TEST_EQUAL( psa_hash_clone( &op_init, &op_target ), PSA_ERROR_BAD_STATE );
+ TEST_EQUAL( psa_hash_clone( &op_finished, &op_target ),
+ PSA_ERROR_BAD_STATE );
+ TEST_EQUAL( psa_hash_clone( &op_aborted, &op_target ),
+ PSA_ERROR_BAD_STATE );
+
+exit:
+ psa_hash_abort( &op_target );
+ psa_hash_abort( &op_init );
+ psa_hash_abort( &op_setup );
+ psa_hash_abort( &op_finished );
+ psa_hash_abort( &op_aborted );
+ mbedtls_psa_crypto_free( );
+}
+/* END_CASE */
+
/* BEGIN_CASE */
void mac_operation_init( )
{
diff --git a/tests/suites/test_suite_psa_crypto_hash.function b/tests/suites/test_suite_psa_crypto_hash.function
index bdb2f98..8abd4e2 100644
--- a/tests/suites/test_suite_psa_crypto_hash.function
+++ b/tests/suites/test_suite_psa_crypto_hash.function
@@ -67,6 +67,7 @@
unsigned char actual_hash[PSA_HASH_MAX_SIZE];
size_t actual_hash_length;
psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
+ psa_hash_operation_t operation2 = PSA_HASH_OPERATION_INIT;
uint32_t len = 0;
PSA_ASSERT( psa_crypto_init( ) );
@@ -78,16 +79,23 @@
PSA_ASSERT( psa_hash_update( &operation,
input->x, len ) );
+ PSA_ASSERT( psa_hash_clone( &operation, &operation2 ) );
PSA_ASSERT( psa_hash_update( &operation,
input->x + len, input->len - len ) );
+ PSA_ASSERT( psa_hash_update( &operation2,
+ input->x + len, input->len - len ) );
PSA_ASSERT( psa_hash_finish( &operation,
actual_hash, sizeof( actual_hash ),
&actual_hash_length ) );
-
ASSERT_COMPARE( expected_hash->x, expected_hash->len,
actual_hash, actual_hash_length );
+ PSA_ASSERT( psa_hash_finish( &operation2,
+ actual_hash, sizeof( actual_hash ),
+ &actual_hash_length ) );
+ ASSERT_COMPARE( expected_hash->x, expected_hash->len,
+ actual_hash, actual_hash_length );
} while( len++ != input->len );
exit: