Commit changes to hmac to not use MD abstraction
this PR is part of efforts to use "lower level" mbedTLS APIs vs "higher level" abstract APIs.
diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h
index 74e1146..8e332b5 100644
--- a/include/psa/crypto_struct.h
+++ b/include/psa/crypto_struct.h
@@ -75,6 +75,16 @@
} ctx;
};
+
+typedef struct {
+ unsigned int block_size;
+ /** The hash context. */
+ struct psa_hash_operation_s hash_ctx;
+ /** The HMAC part of the context. */
+ void *hmac_ctx;
+} psa_hmac_internal_data;
+
+
struct psa_mac_operation_s
{
psa_algorithm_t alg;
@@ -89,7 +99,7 @@
{
unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
#if defined(MBEDTLS_MD_C)
- mbedtls_md_context_t hmac;
+ psa_hmac_internal_data hmac;
#endif
#if defined(MBEDTLS_CMAC_C)
mbedtls_cipher_context_t cmac;
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 18cd44c..5c9a828 100755
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -996,7 +996,16 @@
default:
#if defined(MBEDTLS_MD_C)
if( PSA_ALG_IS_HMAC( operation->alg ) )
- mbedtls_md_free( &operation->ctx.hmac );
+ {
+ psa_hash_abort( &operation->ctx.hmac.hash_ctx );
+ if ( operation->ctx.hmac.hmac_ctx != NULL )
+ {
+ mbedtls_zeroize( operation->ctx.hmac.hmac_ctx,
+ sizeof( operation->ctx.hmac.block_size * 2 ) );
+ mbedtls_free( operation->ctx.hmac.hmac_ctx );
+ operation->ctx.hmac.block_size = 0;
+ }
+ }
else
#endif /* MBEDTLS_MD_C */
return( PSA_ERROR_NOT_SUPPORTED );
@@ -1015,11 +1024,13 @@
psa_key_slot_t key,
psa_algorithm_t alg )
{
- int ret = MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
+ int ret = 0;
psa_status_t status;
key_slot_t *slot;
psa_key_type_t key_type;
size_t key_bits;
+ size_t keylen;
+ uint8_t* key_ptr = NULL;
const mbedtls_cipher_info_t *cipher_info = NULL;
operation->alg = 0;
@@ -1027,11 +1038,19 @@
operation->iv_set = 0;
operation->iv_required = 1;
operation->has_input = 0;
+ operation->key_usage_sign = 0;
+ operation->key_usage_verify = 0;
status = psa_get_key_information( key, &key_type, &key_bits );
if( status != PSA_SUCCESS )
return( status );
+
slot = &global_data.key_slots[key];
+ if (slot->type == PSA_KEY_TYPE_NONE)
+ return(PSA_ERROR_EMPTY_SLOT);
+
+ key_ptr = slot->data.raw.data;
+ keylen = slot->data.raw.bytes;
if( ( slot->policy.usage & PSA_KEY_USAGE_SIGN ) != 0 )
operation->key_usage_sign = 1;
@@ -1064,28 +1083,78 @@
#if defined(MBEDTLS_MD_C)
if( PSA_ALG_IS_HMAC( alg ) )
{
+ unsigned char sum[MBEDTLS_MD_MAX_SIZE];
+ unsigned char *ipad, *opad;
+ size_t i;
+ size_t sum_size = MBEDTLS_MD_MAX_SIZE;
const mbedtls_md_info_t *md_info =
mbedtls_md_info_from_psa( PSA_ALG_HMAC_HASH( alg ) );
+
if( md_info == NULL )
return( PSA_ERROR_NOT_SUPPORTED );
if( key_type != PSA_KEY_TYPE_HMAC )
return( PSA_ERROR_INVALID_ARGUMENT );
+
operation->iv_required = 0;
- operation->mac_size = mbedtls_md_get_size( md_info );
- mbedtls_md_init( &operation->ctx.hmac );
- ret = mbedtls_md_setup( &operation->ctx.hmac, md_info, 1 );
- if( ret != 0 )
- break;
- ret = mbedtls_md_hmac_starts( &operation->ctx.hmac,
- slot->data.raw.data,
- slot->data.raw.bytes );
+ operation->mac_size = md_info->size;
+ operation->ctx.hmac.block_size = md_info->block_size;
+ operation->ctx.hmac.hmac_ctx = mbedtls_calloc( 2,
+ md_info->block_size );
+ if( operation->ctx.hmac.hmac_ctx == NULL )
+ {
+ ret = MBEDTLS_ERR_MD_ALLOC_FAILED;
+ goto cleanup;
+ }
+
+ status = psa_hash_start( &operation->ctx.hmac.hash_ctx,
+ PSA_ALG_HMAC_HASH( alg ) );
+ if( status != PSA_SUCCESS )
+ goto cleanup;
+
+ if( key_bits / 8 > (size_t) operation->ctx.hmac.block_size )
+ {
+ status = psa_hash_update(&operation->ctx.hmac.hash_ctx,
+ key_ptr, slot->data.raw.bytes);
+ if( status != PSA_SUCCESS )
+ goto cleanup;
+ status = psa_hash_finish(&operation->ctx.hmac.hash_ctx, sum,
+ sum_size, &sum_size);
+ if ( status != PSA_SUCCESS )
+ goto cleanup;
+
+ keylen = sum_size;
+ key_ptr = sum;
+ }
+
+ ipad = ( unsigned char * ) operation->ctx.hmac.hmac_ctx;
+ opad = ( unsigned char * ) operation->ctx.hmac.hmac_ctx +
+ operation->ctx.hmac.block_size;
+
+ memset( ipad, 0x36, operation->ctx.hmac.block_size );
+ memset( opad, 0x5C, operation->ctx.hmac.block_size );
+
+ for( i = 0; i < keylen; i++ )
+ {
+ ipad[i] = ( unsigned char )( ipad[i] ^ key_ptr[i] );
+ opad[i] = ( unsigned char )( opad[i] ^ key_ptr[i] );
+ }
+
+ status = psa_hash_start( &operation->ctx.hmac.hash_ctx,
+ PSA_ALG_HMAC_HASH( alg ) );
+ if( status != PSA_SUCCESS )
+ goto cleanup;
+
+ status = psa_hash_update( &operation->ctx.hmac.hash_ctx, ipad,
+ operation->ctx.hmac.block_size );
+ if( status != PSA_SUCCESS )
+ goto cleanup;
break;
}
else
#endif /* MBEDTLS_MD_C */
return( PSA_ERROR_NOT_SUPPORTED );
}
-
+cleanup:
/* If we reach this point, then the algorithm-specific part of the
* context has at least been initialized, and may contain data that
* needs to be wiped on error. */
@@ -1103,7 +1172,8 @@
const uint8_t *input,
size_t input_length )
{
- int ret;
+ int ret = 0 ;
+ psa_status_t status = PSA_SUCCESS;
if( ! operation->key_set )
return( PSA_ERROR_BAD_STATE );
if( operation->iv_required && ! operation->iv_set )
@@ -1122,8 +1192,8 @@
#if defined(MBEDTLS_MD_C)
if( PSA_ALG_IS_HMAC( operation->alg ) )
{
- ret = mbedtls_md_hmac_update( &operation->ctx.hmac,
- input, input_length );
+ status = psa_hash_update( &operation->ctx.hmac.hash_ctx, input,
+ input_length );
}
else
#endif /* MBEDTLS_MD_C */
@@ -1132,9 +1202,14 @@
}
break;
}
- if( ret != 0 )
- psa_mac_abort( operation );
- return( mbedtls_to_psa_error( ret ) );
+ if ( ( ret != 0 ) || ( status != PSA_SUCCESS ) )
+ {
+ psa_mac_abort(operation);
+ if (ret != 0)
+ status = mbedtls_to_psa_error(ret);
+ }
+
+ return status;
}
static psa_status_t psa_mac_finish_internal( psa_mac_operation_t *operation,
@@ -1142,7 +1217,8 @@
size_t mac_size,
size_t *mac_length )
{
- int ret;
+ int ret = 0;
+ psa_status_t status = PSA_SUCCESS;
if( ! operation->key_set )
return( PSA_ERROR_BAD_STATE );
if( operation->iv_required && ! operation->iv_set )
@@ -1168,7 +1244,37 @@
#if defined(MBEDTLS_MD_C)
if( PSA_ALG_IS_HMAC( operation->alg ) )
{
- ret = mbedtls_md_hmac_finish( &operation->ctx.hmac, mac );
+ unsigned char tmp[MBEDTLS_MD_MAX_SIZE];
+ unsigned char *opad;
+ size_t hash_size = 0;
+
+ opad = (unsigned char *) operation->ctx.hmac.hmac_ctx +
+ operation->ctx.hmac.block_size;
+
+ status = psa_hash_finish( &operation->ctx.hmac.hash_ctx, tmp,
+ sizeof ( tmp ), &hash_size );
+ if( status != PSA_SUCCESS )
+ goto cleanup;
+
+ status = psa_hash_start( &operation->ctx.hmac.hash_ctx,
+ PSA_ALG_HMAC_HASH( operation->alg ) );
+ if( status != PSA_SUCCESS )
+ goto cleanup;
+
+ status = psa_hash_update( &operation->ctx.hmac.hash_ctx, opad,
+ operation->ctx.hmac.block_size );
+ if( status != PSA_SUCCESS )
+ goto cleanup;
+
+ status = psa_hash_update( &operation->ctx.hmac.hash_ctx, tmp,
+ hash_size);
+ if( status != PSA_SUCCESS )
+ goto cleanup;
+
+ status = psa_hash_finish( &operation->ctx.hmac.hash_ctx, mac,
+ mac_size, mac_length );
+ if( status != PSA_SUCCESS )
+ goto cleanup;
}
else
#endif /* MBEDTLS_MD_C */
@@ -1177,15 +1283,19 @@
}
break;
}
+cleanup:
- if( ret == 0 )
+ if( ( ret == 0 ) && (status == PSA_SUCCESS) )
{
return( psa_mac_abort( operation ) );
}
else
{
psa_mac_abort( operation );
- return( mbedtls_to_psa_error( ret ) );
+ if (ret != 0)
+ status = mbedtls_to_psa_error(ret);
+
+ return status;
}
}
@@ -1197,7 +1307,8 @@
if( !( operation->key_usage_sign ) )
return( PSA_ERROR_NOT_PERMITTED );
- return( psa_mac_finish_internal(operation, mac, mac_size, mac_length ) );
+ return( psa_mac_finish_internal(operation, mac,
+ mac_size, mac_length ) );
}
#define MBEDTLS_PSA_MAC_MAX_SIZE \