Split out CMAC and HMAC code into auxiliary functions
Split algorithm-specific code out of psa_mac_start. This makes the
function easier to read.
The behavior is mostly unchanged. In a few cases, errors before
setting a key trigger a context wipe where they didn't. This is a
marginal performance loss but only cases that are an error in caller
code.
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index c34d621..1eecd3e 100755
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -925,6 +925,7 @@
alg &= ~PSA_ALG_BLOCK_CIPHER_PADDING_MASK;
}
switch( alg )
+
{
case PSA_ALG_STREAM_CIPHER:
mode = MBEDTLS_MODE_STREAM;
@@ -1037,18 +1038,105 @@
return( PSA_SUCCESS );
}
+static int psa_cmac_start( psa_mac_operation_t *operation,
+ size_t key_bits,
+ key_slot_t *slot,
+ const mbedtls_cipher_info_t *cipher_info )
+{
+ int ret;
+
+ operation->mac_size = cipher_info->block_size;
+ operation->iv_required = 0;
+ mbedtls_cipher_init( &operation->ctx.cmac );
+
+ ret = mbedtls_cipher_setup( &operation->ctx.cmac, cipher_info );
+ if( ret != 0 )
+ return( ret );
+
+ ret = mbedtls_cipher_cmac_starts( &operation->ctx.cmac,
+ slot->data.raw.data,
+ key_bits );
+ return( ret );
+}
+
+static int psa_hmac_start( psa_mac_operation_t *operation,
+ psa_key_type_t key_type,
+ size_t key_bits,
+ key_slot_t *slot,
+ psa_algorithm_t alg )
+{
+ unsigned char sum[PSA_CRYPTO_MD_MAX_SIZE];
+ unsigned char ipad[PSA_CRYPTO_MD_BLOCK_SIZE];
+ unsigned char *opad;
+ size_t i;
+ size_t sum_size = MBEDTLS_MD_MAX_SIZE;
+ unsigned int block_size =
+ PSA_HASH_BLOCK_SIZE( ( PSA_ALG_HMAC_HASH( alg ) ) );
+ unsigned int digest_size =
+ PSA_HASH_FINAL_SIZE( ( PSA_ALG_HMAC_HASH( alg ) ) );
+ uint8_t* key_ptr = slot->data.raw.data;
+ size_t key_length = slot->data.raw.bytes;
+ psa_status_t status;
+
+ if( ( block_size == 0 ) || ( digest_size == 0 ) )
+ return( PSA_ERROR_NOT_SUPPORTED );
+
+ if( key_type != PSA_KEY_TYPE_HMAC )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+ operation->iv_required = 0;
+ operation->mac_size = digest_size;
+
+ status = psa_hash_start( &operation->ctx.hmac.hash_ctx,
+ PSA_ALG_HMAC_HASH( alg ) );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ if( key_bits / 8 > (size_t) block_size )
+ {
+ status = psa_hash_update( &operation->ctx.hmac.hash_ctx,
+ key_ptr, slot->data.raw.bytes);
+ if( status != PSA_SUCCESS )
+ return( status );
+ status = psa_hash_finish( &operation->ctx.hmac.hash_ctx,
+ sum, sum_size, &sum_size);
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ key_length = sum_size;
+ key_ptr = sum;
+ }
+
+ opad = (unsigned char *) operation->ctx.hmac.hmac_ctx;
+
+ memset( ipad, 0x36, block_size );
+ memset( opad, 0x5C, block_size );
+
+ for( i = 0; i < key_length; 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 )
+ return( status );
+
+ status = psa_hash_update( &operation->ctx.hmac.hash_ctx, ipad,
+ block_size );
+ return( status );
+}
+
psa_status_t psa_mac_start( psa_mac_operation_t *operation,
psa_key_slot_t key,
psa_algorithm_t alg )
{
- int ret = 0;
psa_status_t status;
key_slot_t *slot;
psa_key_type_t key_type;
size_t key_bits;
- size_t key_length;
- uint8_t* key_ptr = NULL;
- const mbedtls_cipher_info_t *cipher_info = NULL;
+ const mbedtls_cipher_info_t *cipher_info;
operation->alg = 0;
operation->key_set = 0;
@@ -1066,9 +1154,6 @@
if( slot->type == PSA_KEY_TYPE_NONE )
return( PSA_ERROR_EMPTY_SLOT );
- key_ptr = slot->data.raw.data;
- key_length = slot->data.raw.bytes;
-
if( ( slot->policy.usage & PSA_KEY_USAGE_SIGN ) != 0 )
operation->key_usage_sign = 1;
@@ -1086,97 +1171,37 @@
{
#if defined(MBEDTLS_CMAC_C)
case PSA_ALG_CMAC:
- operation->iv_required = 0;
- mbedtls_cipher_init( &operation->ctx.cmac );
- ret = mbedtls_cipher_setup( &operation->ctx.cmac, cipher_info );
- if( ret != 0 )
- break;
- ret = mbedtls_cipher_cmac_starts( &operation->ctx.cmac,
- slot->data.raw.data,
- key_bits );
+ status = mbedtls_to_psa_error( psa_cmac_start( operation,
+ key_bits,
+ slot,
+ cipher_info ) );
break;
#endif /* MBEDTLS_CMAC_C */
default:
#if defined(MBEDTLS_MD_C)
if( PSA_ALG_IS_HMAC( alg ) )
- {
- unsigned char sum[PSA_CRYPTO_MD_MAX_SIZE];
- unsigned char ipad[PSA_CRYPTO_MD_BLOCK_SIZE];
- unsigned char *opad;
- size_t i;
- size_t sum_size = MBEDTLS_MD_MAX_SIZE;
- unsigned int block_size =
- PSA_HASH_BLOCK_SIZE( ( PSA_ALG_HMAC_HASH( alg ) ) );
- unsigned int digest_size =
- PSA_HASH_FINAL_SIZE( ( PSA_ALG_HMAC_HASH( alg ) ) );
-
- if( ( block_size == 0 ) || ( digest_size == 0 ) )
- return( PSA_ERROR_NOT_SUPPORTED );
-
- if( key_type != PSA_KEY_TYPE_HMAC )
- return( PSA_ERROR_INVALID_ARGUMENT );
-
- operation->iv_required = 0;
- operation->mac_size = digest_size;
-
- 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) 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;
-
- key_length = sum_size;
- key_ptr = sum;
- }
-
- opad = (unsigned char *) operation->ctx.hmac.hmac_ctx;
-
- memset( ipad, 0x36, block_size );
- memset( opad, 0x5C, block_size );
-
- for( i = 0; i < key_length; 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,
- block_size );
- if( status != PSA_SUCCESS )
- goto cleanup;
- break;
- }
+ status = psa_hmac_start( operation,
+ key_type, key_bits, slot,
+ alg );
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. */
- operation->alg = alg;
- if( ret != 0 )
+
+ * context may contain data that needs to be wiped on error. */
+ if( status != PSA_SUCCESS )
{
psa_mac_abort(operation);
- if ( ret != 0 )
- status = mbedtls_to_psa_error(ret);
}
+ else
+ {
+ operation->alg = alg;
+ operation->key_set = 1;
+ }
+ return( status );
}
psa_status_t psa_mac_update( psa_mac_operation_t *operation,