Add support for truncated MAC algorithms
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 6fd905c..3411cc8 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -1523,8 +1523,10 @@
size_t key_bits;
psa_key_usage_t usage =
is_sign ? PSA_KEY_USAGE_SIGN : PSA_KEY_USAGE_VERIFY;
+ unsigned char truncated = PSA_MAC_TRUNCATED_LENGTH( alg );
+ psa_algorithm_t full_length_alg = alg & ~PSA_ALG_MAC_TRUNCATION_MASK;
- status = psa_mac_init( operation, alg );
+ status = psa_mac_init( operation, full_length_alg );
if( status != PSA_SUCCESS )
return( status );
if( is_sign )
@@ -1536,10 +1538,11 @@
key_bits = psa_get_key_bits( slot );
#if defined(MBEDTLS_CMAC_C)
- if( alg == PSA_ALG_CMAC )
+ if( full_length_alg == PSA_ALG_CMAC )
{
const mbedtls_cipher_info_t *cipher_info =
- mbedtls_cipher_info_from_psa( alg, slot->type, key_bits, NULL );
+ mbedtls_cipher_info_from_psa( full_length_alg,
+ slot->type, key_bits, NULL );
int ret;
if( cipher_info == NULL )
{
@@ -1553,7 +1556,7 @@
else
#endif /* MBEDTLS_CMAC_C */
#if defined(MBEDTLS_MD_C)
- if( PSA_ALG_IS_HMAC( alg ) )
+ if( PSA_ALG_IS_HMAC( full_length_alg ) )
{
psa_algorithm_t hash_alg = PSA_ALG_HMAC_GET_HASH( alg );
if( hash_alg == 0 )
@@ -1588,6 +1591,24 @@
status = PSA_ERROR_NOT_SUPPORTED;
}
+ if( truncated == 0 )
+ {
+ /* The "normal" case: untruncated algorithm. Nothing to do. */
+ }
+ else if( truncated < 4 )
+ {
+ /* Too small to make any sense. Reject. 4 bytes is too small for
+ * security but ancient protocols with 32-bit MACs do exist. */
+ status = PSA_ERROR_NOT_SUPPORTED;
+ }
+ else if( truncated > operation->mac_size )
+ {
+ /* It's impossible to "truncate" to a larger length. */
+ status = PSA_ERROR_INVALID_ARGUMENT;
+ }
+ else
+ operation->mac_size = truncated;
+
exit:
if( status != PSA_SUCCESS )
{
@@ -1682,7 +1703,11 @@
if( status != PSA_SUCCESS )
goto exit;
- status = psa_hash_finish( &hmac->hash_ctx, mac, mac_size, &hash_size );
+ status = psa_hash_finish( &hmac->hash_ctx, tmp, sizeof( tmp ), &hash_size );
+ if( status != PSA_SUCCESS )
+ goto exit;
+
+ memcpy( mac, tmp, mac_size );
exit:
mbedtls_zeroize( tmp, hash_size );
@@ -1705,7 +1730,11 @@
#if defined(MBEDTLS_CMAC_C)
if( operation->alg == PSA_ALG_CMAC )
{
- int ret = mbedtls_cipher_cmac_finish( &operation->ctx.cmac, mac );
+ uint8_t tmp[PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE];
+ int ret = mbedtls_cipher_cmac_finish( &operation->ctx.cmac, tmp );
+ if( ret == 0 )
+ memcpy( mac, tmp, mac_size );
+ mbedtls_zeroize( tmp, sizeof( tmp ) );
return( mbedtls_to_psa_error( ret ) );
}
else
@@ -1714,7 +1743,7 @@
if( PSA_ALG_IS_HMAC( operation->alg ) )
{
return( psa_hmac_finish_internal( &operation->ctx.hmac,
- mac, mac_size ) );
+ mac, operation->mac_size ) );
}
else
#endif /* MBEDTLS_MD_C */
@@ -1793,6 +1822,8 @@
else
psa_mac_abort( operation );
+ mbedtls_zeroize( actual_mac, mac_length );
+
return( status );
}