diff --git a/library/psa_crypto.c b/library/psa_crypto.c index f91e5c322..fc055011a 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -35,6 +35,7 @@ #include "psa_crypto_driver_wrappers.h" #include "psa_crypto_ecp.h" #include "psa_crypto_hash.h" +#include "psa_crypto_mac.h" #include "psa_crypto_rsa.h" #include "psa_crypto_ecp.h" #if defined(MBEDTLS_PSA_CRYPTO_SE_C) @@ -2297,35 +2298,6 @@ psa_status_t psa_hash_clone( const psa_hash_operation_t *source_operation, /* MAC */ /****************************************************************/ -#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) -static size_t psa_get_hash_block_size( psa_algorithm_t alg ) -{ - switch( alg ) - { - case PSA_ALG_MD2: - return( 16 ); - case PSA_ALG_MD4: - return( 64 ); - case PSA_ALG_MD5: - return( 64 ); - case PSA_ALG_RIPEMD160: - return( 64 ); - case PSA_ALG_SHA_1: - return( 64 ); - case PSA_ALG_SHA_224: - return( 64 ); - case PSA_ALG_SHA_256: - return( 64 ); - case PSA_ALG_SHA_384: - return( 128 ); - case PSA_ALG_SHA_512: - return( 128 ); - default: - return( 0 ); - } -} -#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) */ - /* Initialize the MAC operation structure. Once this function has been * called, psa_mac_abort can run and will do the right thing. */ static psa_status_t psa_mac_init( mbedtls_psa_mac_operation_t *operation, @@ -2368,14 +2340,6 @@ static psa_status_t psa_mac_init( mbedtls_psa_mac_operation_t *operation, return( status ); } -#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) -static psa_status_t psa_hmac_abort_internal( psa_hmac_internal_data *hmac ) -{ - mbedtls_platform_zeroize( hmac->opad, sizeof( hmac->opad ) ); - return( psa_hash_abort( &hmac->hash_ctx ) ); -} -#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ - psa_status_t psa_mac_abort( psa_mac_operation_t *psa_operation ) { /* Temporary recast to avoid changing a lot of lines */ @@ -2451,72 +2415,6 @@ exit: } #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ -#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) -static psa_status_t psa_hmac_setup_internal( psa_hmac_internal_data *hmac, - const uint8_t *key, - size_t key_length, - psa_algorithm_t hash_alg ) -{ - uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; - size_t i; - size_t hash_size = PSA_HASH_LENGTH( hash_alg ); - size_t block_size = psa_get_hash_block_size( hash_alg ); - psa_status_t status; - - hmac->alg = hash_alg; - - /* Sanity checks on block_size, to guarantee that there won't be a buffer - * overflow below. This should never trigger if the hash algorithm - * is implemented correctly. */ - /* The size checks against the ipad and opad buffers cannot be written - * `block_size > sizeof( ipad ) || block_size > sizeof( hmac->opad )` - * because that triggers -Wlogical-op on GCC 7.3. */ - if( block_size > sizeof( ipad ) ) - return( PSA_ERROR_NOT_SUPPORTED ); - if( block_size > sizeof( hmac->opad ) ) - return( PSA_ERROR_NOT_SUPPORTED ); - if( block_size < hash_size ) - return( PSA_ERROR_NOT_SUPPORTED ); - - if( key_length > block_size ) - { - status = psa_hash_compute( hash_alg, key, key_length, - ipad, sizeof( ipad ), &key_length ); - if( status != PSA_SUCCESS ) - goto cleanup; - } - /* A 0-length key is not commonly used in HMAC when used as a MAC, - * but it is permitted. It is common when HMAC is used in HKDF, for - * example. Don't call `memcpy` in the 0-length because `key` could be - * an invalid pointer which would make the behavior undefined. */ - else if( key_length != 0 ) - memcpy( ipad, key, key_length ); - - /* ipad contains the key followed by garbage. Xor and fill with 0x36 - * to create the ipad value. */ - for( i = 0; i < key_length; i++ ) - ipad[i] ^= 0x36; - memset( ipad + key_length, 0x36, block_size - key_length ); - - /* Copy the key material from ipad to opad, flipping the requisite bits, - * and filling the rest of opad with the requisite constant. */ - for( i = 0; i < key_length; i++ ) - hmac->opad[i] = ipad[i] ^ 0x36 ^ 0x5C; - memset( hmac->opad + key_length, 0x5C, block_size - key_length ); - - status = psa_hash_setup( &hmac->hash_ctx, hash_alg ); - if( status != PSA_SUCCESS ) - goto cleanup; - - status = psa_hash_update( &hmac->hash_ctx, ipad, block_size ); - -cleanup: - mbedtls_platform_zeroize( ipad, sizeof( ipad ) ); - - return( status ); -} -#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ - static psa_status_t psa_mac_setup( psa_mac_operation_t *psa_operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg, @@ -2682,46 +2580,6 @@ psa_status_t psa_mac_update( psa_mac_operation_t *psa_operation, return( status ); } -#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) -static psa_status_t psa_hmac_finish_internal( psa_hmac_internal_data *hmac, - uint8_t *mac, - size_t mac_size ) -{ - uint8_t tmp[MBEDTLS_MD_MAX_SIZE]; - psa_algorithm_t hash_alg = hmac->alg; - size_t hash_size = 0; - size_t block_size = psa_get_hash_block_size( hash_alg ); - psa_status_t status; - - status = psa_hash_finish( &hmac->hash_ctx, tmp, sizeof( tmp ), &hash_size ); - if( status != PSA_SUCCESS ) - return( status ); - /* From here on, tmp needs to be wiped. */ - - status = psa_hash_setup( &hmac->hash_ctx, hash_alg ); - if( status != PSA_SUCCESS ) - goto exit; - - status = psa_hash_update( &hmac->hash_ctx, hmac->opad, block_size ); - if( status != PSA_SUCCESS ) - goto exit; - - status = psa_hash_update( &hmac->hash_ctx, tmp, hash_size ); - if( status != PSA_SUCCESS ) - goto exit; - - 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_platform_zeroize( tmp, hash_size ); - return( status ); -} -#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ - static psa_status_t psa_mac_finish_internal( mbedtls_psa_mac_operation_t *operation, uint8_t *mac, size_t mac_size ) diff --git a/library/psa_crypto_mac.c b/library/psa_crypto_mac.c index 169be3a45..b09efea59 100644 --- a/library/psa_crypto_mac.c +++ b/library/psa_crypto_mac.c @@ -25,6 +25,7 @@ #include #include "psa_crypto_core.h" #include "psa_crypto_mac.h" +#include #include #include @@ -40,6 +41,143 @@ #define BUILTIN_ALG_HMAC 1 #endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || defined(PSA_CRYPTO_DRIVER_TEST) +static size_t psa_get_hash_block_size( psa_algorithm_t alg ) +{ + switch( alg ) + { + case PSA_ALG_MD2: + return( 16 ); + case PSA_ALG_MD4: + return( 64 ); + case PSA_ALG_MD5: + return( 64 ); + case PSA_ALG_RIPEMD160: + return( 64 ); + case PSA_ALG_SHA_1: + return( 64 ); + case PSA_ALG_SHA_224: + return( 64 ); + case PSA_ALG_SHA_256: + return( 64 ); + case PSA_ALG_SHA_384: + return( 128 ); + case PSA_ALG_SHA_512: + return( 128 ); + default: + return( 0 ); + } +} + +psa_status_t psa_hmac_abort_internal( psa_hmac_internal_data *hmac ) +{ + mbedtls_platform_zeroize( hmac->opad, sizeof( hmac->opad ) ); + return( psa_hash_abort( &hmac->hash_ctx ) ); +} + +psa_status_t psa_hmac_setup_internal( psa_hmac_internal_data *hmac, + const uint8_t *key, + size_t key_length, + psa_algorithm_t hash_alg ) +{ + uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; + size_t i; + size_t hash_size = PSA_HASH_LENGTH( hash_alg ); + size_t block_size = psa_get_hash_block_size( hash_alg ); + psa_status_t status; + + hmac->alg = hash_alg; + + /* Sanity checks on block_size, to guarantee that there won't be a buffer + * overflow below. This should never trigger if the hash algorithm + * is implemented correctly. */ + /* The size checks against the ipad and opad buffers cannot be written + * `block_size > sizeof( ipad ) || block_size > sizeof( hmac->opad )` + * because that triggers -Wlogical-op on GCC 7.3. */ + if( block_size > sizeof( ipad ) ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( block_size > sizeof( hmac->opad ) ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( block_size < hash_size ) + return( PSA_ERROR_NOT_SUPPORTED ); + + if( key_length > block_size ) + { + status = psa_hash_compute( hash_alg, key, key_length, + ipad, sizeof( ipad ), &key_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + } + /* A 0-length key is not commonly used in HMAC when used as a MAC, + * but it is permitted. It is common when HMAC is used in HKDF, for + * example. Don't call `memcpy` in the 0-length because `key` could be + * an invalid pointer which would make the behavior undefined. */ + else if( key_length != 0 ) + memcpy( ipad, key, key_length ); + + /* ipad contains the key followed by garbage. Xor and fill with 0x36 + * to create the ipad value. */ + for( i = 0; i < key_length; i++ ) + ipad[i] ^= 0x36; + memset( ipad + key_length, 0x36, block_size - key_length ); + + /* Copy the key material from ipad to opad, flipping the requisite bits, + * and filling the rest of opad with the requisite constant. */ + for( i = 0; i < key_length; i++ ) + hmac->opad[i] = ipad[i] ^ 0x36 ^ 0x5C; + memset( hmac->opad + key_length, 0x5C, block_size - key_length ); + + status = psa_hash_setup( &hmac->hash_ctx, hash_alg ); + if( status != PSA_SUCCESS ) + goto cleanup; + + status = psa_hash_update( &hmac->hash_ctx, ipad, block_size ); + +cleanup: + mbedtls_platform_zeroize( ipad, sizeof( ipad ) ); + + return( status ); +} + +psa_status_t psa_hmac_finish_internal( psa_hmac_internal_data *hmac, + uint8_t *mac, + size_t mac_size ) +{ + uint8_t tmp[MBEDTLS_MD_MAX_SIZE]; + psa_algorithm_t hash_alg = hmac->alg; + size_t hash_size = 0; + size_t block_size = psa_get_hash_block_size( hash_alg ); + psa_status_t status; + + status = psa_hash_finish( &hmac->hash_ctx, tmp, sizeof( tmp ), &hash_size ); + if( status != PSA_SUCCESS ) + return( status ); + /* From here on, tmp needs to be wiped. */ + + status = psa_hash_setup( &hmac->hash_ctx, hash_alg ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_hash_update( &hmac->hash_ctx, hmac->opad, block_size ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_hash_update( &hmac->hash_ctx, tmp, hash_size ); + if( status != PSA_SUCCESS ) + goto exit; + + 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_platform_zeroize( tmp, hash_size ); + return( status ); +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC || PSA_CRYPTO_DRIVER_TEST */ + /* Implement the PSA driver MAC interface on top of mbed TLS if either the * software driver or the test driver requires it. */ #if defined(MBEDTLS_PSA_BUILTIN_MAC) || defined(PSA_CRYPTO_DRIVER_TEST) @@ -54,7 +192,7 @@ static psa_status_t mac_compute( size_t mac_size, size_t *mac_length ) { - /* To be fleshed out in a subsequent commit */ + /* One-shot MAC has not been implemented in this PSA implementation yet. */ (void) attributes; (void) key_buffer; (void) key_buffer_size; diff --git a/library/psa_crypto_mac.h b/library/psa_crypto_mac.h index 4da60bf40..d92351160 100644 --- a/library/psa_crypto_mac.h +++ b/library/psa_crypto_mac.h @@ -23,6 +23,17 @@ #include +psa_status_t psa_hmac_setup_internal( psa_hmac_internal_data *hmac, + const uint8_t *key, + size_t key_length, + psa_algorithm_t hash_alg ); + +psa_status_t psa_hmac_finish_internal( psa_hmac_internal_data *hmac, + uint8_t *mac, + size_t mac_size ); + +psa_status_t psa_hmac_abort_internal( psa_hmac_internal_data *hmac ); + /** Calculate the MAC (message authentication code) of a message using Mbed TLS. * * \note The signature of this function is that of a PSA driver mac_compute