Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PSA Crypto driver delegation for hashing functions #4043

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ChangeLog.d/psa-crypto-hash-acceleration.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Features
* Hashing operations executed through the PSA API can now be accelerated
with a PSA Crypto driver.
6 changes: 4 additions & 2 deletions include/psa/crypto_struct.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,11 @@ typedef struct {
struct psa_hash_operation_s
{
psa_algorithm_t alg;
unsigned int mbedtls_in_use : 1; /* Indicates mbed TLS is handling the operation. */
union
{
unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
uint32_t dummy; /* Enable easier initializing of the union. */
psa_operation_driver_context_t driver;
#if defined(MBEDTLS_MD2_C)
mbedtls_md2_context md2;
#endif
Expand All @@ -117,7 +119,7 @@ struct psa_hash_operation_s
} ctx;
};

#define PSA_HASH_OPERATION_INIT {0, {0}}
#define PSA_HASH_OPERATION_INIT {0, 0, {0}}
static inline struct psa_hash_operation_s psa_hash_operation_init( void )
{
const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT;
Expand Down
122 changes: 98 additions & 24 deletions library/psa_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -2537,6 +2537,20 @@ static const mbedtls_md_info_t *mbedtls_md_info_from_psa( psa_algorithm_t alg )

psa_status_t psa_hash_abort( psa_hash_operation_t *operation )
{
if( operation->alg == 0 )
{
/* The object has (apparently) been initialized but it is not
* in use. It's ok to call abort on such an object, and there's
* nothing to do. */
return( PSA_SUCCESS );
}

if( operation->mbedtls_in_use == 0 )
{
psa_driver_wrapper_hash_abort( &operation->ctx.driver );
goto exit;
}

switch( operation->alg )
{
case 0:
Expand Down Expand Up @@ -2592,13 +2606,16 @@ psa_status_t psa_hash_abort( psa_hash_operation_t *operation )
default:
return( PSA_ERROR_BAD_STATE );
}

exit:
operation->alg = 0;
return( PSA_SUCCESS );
}

psa_status_t psa_hash_setup( psa_hash_operation_t *operation,
psa_algorithm_t alg )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;

/* A context must be freshly initialized before it can be set up. */
Expand All @@ -2607,6 +2624,17 @@ psa_status_t psa_hash_setup( psa_hash_operation_t *operation,
return( PSA_ERROR_BAD_STATE );
}

operation->mbedtls_in_use = 0;
Copy link
Contributor

@ronald-cron-arm ronald-cron-arm Jan 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not aligned with the organization of the PSA implementation with respect to the PSA driver interface that we are currently trying to move to. The code organization is described in the psa-crypto-implementation-structure.md document in PR #3933 and an example of its application for multi-part operation can be found here (for ciphers).
Thus this is likely that this PR will need some significant refactoring. It is also probably better to not start any refactoring before PR #3933 is merged.

status = psa_driver_wrapper_hash_setup( &operation->ctx.driver,
alg );
if( status != PSA_ERROR_NOT_SUPPORTED )
{
goto exit;
}

/* fell through, try mbed TLS functions */
operation->mbedtls_in_use = 1;

switch( alg )
{
#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD2)
Expand Down Expand Up @@ -2668,24 +2696,39 @@ psa_status_t psa_hash_setup( psa_hash_operation_t *operation,
PSA_ERROR_NOT_SUPPORTED :
PSA_ERROR_INVALID_ARGUMENT );
}
if( ret == 0 )
status = mbedtls_to_psa_error( ret );

exit:
if( status == PSA_SUCCESS )
operation->alg = alg;
else
psa_hash_abort( operation );
return( mbedtls_to_psa_error( ret ) );
return( status );
}

psa_status_t psa_hash_update( psa_hash_operation_t *operation,
const uint8_t *input,
size_t input_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;

if ( operation->alg == 0 )
return( PSA_ERROR_BAD_STATE );

/* Don't require hash implementations to behave correctly on a
* zero-length input, which may have an invalid pointer. */
if( input_length == 0 )
return( PSA_SUCCESS );

if( operation->mbedtls_in_use == 0 )
{
status = psa_driver_wrapper_hash_update( &operation->ctx.driver,
input,
input_length );
goto exit;
}

switch( operation->alg )
{
#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD2)
Expand Down Expand Up @@ -2747,20 +2790,26 @@ psa_status_t psa_hash_update( psa_hash_operation_t *operation,
return( PSA_ERROR_BAD_STATE );
}

if( ret != 0 )
status = mbedtls_to_psa_error( ret );

exit:
if( status != PSA_SUCCESS )
psa_hash_abort( operation );
return( mbedtls_to_psa_error( ret ) );
return( status );
}

psa_status_t psa_hash_finish( psa_hash_operation_t *operation,
uint8_t *hash,
size_t hash_size,
size_t *hash_length )
{
psa_status_t status;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t actual_hash_length = PSA_HASH_SIZE( operation->alg );

if ( operation->alg == 0 )
return( PSA_ERROR_BAD_STATE );

/* Fill the output buffer with something that isn't a valid hash
* (barring an attack on the hash and deliberately-crafted input),
* in case the caller doesn't check the return status properly. */
Expand All @@ -2776,6 +2825,15 @@ psa_status_t psa_hash_finish( psa_hash_operation_t *operation,
goto exit;
}

if( operation->mbedtls_in_use == 0 )
{
status = psa_driver_wrapper_hash_finish( &operation->ctx.driver,
hash,
hash_size,
hash_length );
goto exit;
}

switch( operation->alg )
{
#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD2)
Expand Down Expand Up @@ -2867,6 +2925,12 @@ psa_status_t psa_hash_compute( psa_algorithm_t alg,
psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;

status = psa_driver_wrapper_hash_compute( alg, input, input_length,
hash, hash_size, hash_length );

if( status != PSA_ERROR_NOT_SUPPORTED )
return( status );

*hash_length = hash_size;
status = psa_hash_setup( &operation, alg );
if( status != PSA_SUCCESS )
Expand All @@ -2890,37 +2954,45 @@ 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;
uint8_t actual_hash[MBEDTLS_MD_MAX_SIZE];
size_t actual_hash_length;
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;
status = psa_hash_compute( alg, input, input_length,
actual_hash, sizeof(actual_hash),
&actual_hash_length );

exit:
if( status == PSA_SUCCESS )
status = psa_hash_abort( &operation );
else
psa_hash_abort( &operation );
return( status );
if( status != PSA_SUCCESS )
return( status );
if( actual_hash_length != hash_length )
return( PSA_ERROR_INVALID_SIGNATURE );
if( safer_memcmp( hash, actual_hash, actual_hash_length ) != 0 )
return( PSA_ERROR_INVALID_SIGNATURE );
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 )
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;

/* To clone, the source must be in progress and the target must be free */
if( source_operation->alg == 0 || target_operation->alg != 0 )
return( PSA_ERROR_BAD_STATE );

if ( source_operation->mbedtls_in_use == 0 )
{
status = psa_driver_wrapper_hash_clone( &source_operation->ctx.driver,
&target_operation->ctx.driver);
if ( status == PSA_SUCCESS )
goto exit;
/* Cloning a hash operation using a driver needs to succeed since only
* that specific driver knows the context structure. */
return( status );
}

switch( source_operation->alg )
{
case 0:
return( PSA_ERROR_BAD_STATE );
#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD2)
case PSA_ALG_MD2:
mbedtls_md2_clone( &target_operation->ctx.md2,
Expand Down Expand Up @@ -2979,6 +3051,8 @@ psa_status_t psa_hash_clone( const psa_hash_operation_t *source_operation,
return( PSA_ERROR_NOT_SUPPORTED );
}

exit:
target_operation->mbedtls_in_use = source_operation->mbedtls_in_use;
target_operation->alg = source_operation->alg;
return( PSA_SUCCESS );
}
Expand Down
Loading