Rework MAC algorithm / key type validation
Reworked the validation of MAC algorithm with the used key type by introducing psa_mac_key_can_do, which guarantees that PSA_MAC_LENGTH can be called successfully after validation of the algorithm and key type. This means psa_get_mac_output_length is no longer required. Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
This commit is contained in:
parent
4ff9a29686
commit
f9f7fdfe49
@ -545,58 +545,44 @@ static inline size_t psa_get_key_slot_bits( const psa_key_slot_t *slot )
|
||||
return( slot->attr.bits );
|
||||
}
|
||||
|
||||
/** Return the output MAC length of a MAC algorithm, in bytes
|
||||
/** Check whether a given key type is valid for use with a given MAC algorithm
|
||||
*
|
||||
* \param[in] algorithm The specific (non-wildcard) MAC algorithm.
|
||||
* Upon successful return of this function, the behavioud of #PSA_MAC_LENGTH
|
||||
* will be defined when called with the validated \p algorithm and \p key_type
|
||||
*
|
||||
* \param[in] algorithm The specific MAC algorithm (can be wildcard).
|
||||
* \param[in] key_type The key type of the key to be used with the
|
||||
* \p algorithm.
|
||||
* \param[out] length The calculated output length of the given MAC
|
||||
* \p algorithm when used with a key corresponding to
|
||||
* the given \p key_type
|
||||
*
|
||||
* \retval #PSA_SUCCESS
|
||||
* The \p length has been successfully calculated
|
||||
* The \p key_type is valid for use with the \p algorithm
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* \p algorithm is not a valid, specific MAC algorithm recognized and
|
||||
* supported by this core, or \p key_type describes a key which is
|
||||
* inconsistent with the specified \p algorithm.
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* \p algorithm tries to truncate the MAC to a size which would be
|
||||
* larger than the underlying algorithm's maximum output length.
|
||||
* The \p key_type is not valid for use with the \p algorithm
|
||||
*/
|
||||
MBEDTLS_STATIC_TESTABLE psa_status_t psa_get_mac_output_length(
|
||||
MBEDTLS_STATIC_TESTABLE psa_status_t psa_mac_key_can_do(
|
||||
psa_algorithm_t algorithm,
|
||||
psa_key_type_t key_type,
|
||||
size_t *length )
|
||||
psa_key_type_t key_type )
|
||||
{
|
||||
/* Get the default length for the algorithm and key combination. None of the
|
||||
* currently supported algorithms have a default output length dependent on
|
||||
* key size, so setting it to a bogus value is OK. */
|
||||
size_t default_length = PSA_MAC_LENGTH( key_type, 0,
|
||||
PSA_ALG_FULL_LENGTH_MAC( algorithm ) );
|
||||
|
||||
/* PSA_MAC_LENGTH, when called on a full-length algorithm identifier, can
|
||||
* currently return either 0 (unknown algorithm) or 1 (cipher-MAC with
|
||||
* stream cipher) in cases where the key type / algorithm combination would
|
||||
* be invalid. */
|
||||
if( default_length == 0 || default_length == 1 )
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
|
||||
/* Output the expected (potentially truncated) length as long as it can
|
||||
* actually be output by the algorithm. Truncation length of '0' means
|
||||
* default output length of the keytype-algorithm combination. */
|
||||
if( PSA_MAC_TRUNCATED_LENGTH( algorithm ) == 0 )
|
||||
{
|
||||
*length = default_length;
|
||||
return( PSA_SUCCESS );
|
||||
if( PSA_ALG_IS_HMAC( algorithm ) ) {
|
||||
if( key_type == PSA_KEY_TYPE_HMAC )
|
||||
return( PSA_SUCCESS );
|
||||
}
|
||||
else if( PSA_MAC_TRUNCATED_LENGTH( algorithm ) <= default_length )
|
||||
|
||||
if( PSA_ALG_IS_BLOCK_CIPHER_MAC( algorithm ) )
|
||||
{
|
||||
*length = PSA_MAC_TRUNCATED_LENGTH( algorithm );
|
||||
return( PSA_SUCCESS );
|
||||
/* Check that we're calling PSA_BLOCK_CIPHER_BLOCK_LENGTH with a cipher
|
||||
* key. */
|
||||
if( ( key_type & PSA_KEY_TYPE_CATEGORY_MASK ) ==
|
||||
PSA_KEY_TYPE_CATEGORY_SYMMETRIC )
|
||||
{
|
||||
/* PSA_BLOCK_CIPHER_BLOCK_LENGTH returns 1 for stream ciphers and
|
||||
* the block length (larger than 1) for block ciphers. */
|
||||
if( PSA_BLOCK_CIPHER_BLOCK_LENGTH( key_type ) > 1 )
|
||||
return( PSA_SUCCESS );
|
||||
}
|
||||
}
|
||||
else
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
}
|
||||
|
||||
/** Try to allocate a buffer to an empty key slot.
|
||||
@ -765,28 +751,19 @@ static psa_algorithm_t psa_key_policy_algorithm_intersection(
|
||||
( PSA_ALG_FULL_LENGTH_MAC( alg1 ) ==
|
||||
PSA_ALG_FULL_LENGTH_MAC( alg2 ) ) )
|
||||
{
|
||||
/* Calculate the actual requested output length for both sides. In case
|
||||
* of at-least-this-length wildcard algorithms, the requested output
|
||||
* length is the shortest allowed length. */
|
||||
size_t alg1_len = 0;
|
||||
size_t alg2_len = 0;
|
||||
if( PSA_SUCCESS != psa_get_mac_output_length(
|
||||
PSA_ALG_TRUNCATED_MAC( alg1,
|
||||
PSA_MAC_TRUNCATED_LENGTH( alg1 ) ),
|
||||
key_type,
|
||||
&alg1_len ) )
|
||||
{
|
||||
/* Validate the combination of key type and algorithm. Since the base
|
||||
* algorithm of alg1 and alg2 are the same, we only need this once. */
|
||||
if( PSA_SUCCESS != psa_mac_key_can_do( alg1, key_type ) )
|
||||
return( 0 );
|
||||
}
|
||||
if( PSA_SUCCESS != psa_get_mac_output_length(
|
||||
PSA_ALG_TRUNCATED_MAC( alg2,
|
||||
PSA_MAC_TRUNCATED_LENGTH( alg2 ) ),
|
||||
key_type,
|
||||
&alg2_len ) )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Get the output length for the algorithm and key combination. None of
|
||||
* the currently supported algorithms have an output length dependent on
|
||||
* actual key size, so setting it to a bogus value is currently OK.
|
||||
* Note that for at-least-this-length wildcard algorithms, the output
|
||||
* length is set to the shortest allowed length, which allows us to
|
||||
* calculate the most restrictive tag length for the intersection. */
|
||||
size_t alg1_len = PSA_MAC_LENGTH( key_type, 0, alg1 );
|
||||
size_t alg2_len = PSA_MAC_LENGTH( key_type, 0, alg2 );
|
||||
size_t max_len = alg1_len > alg2_len ? alg1_len : alg2_len;
|
||||
|
||||
/* If both are wildcards, return most restrictive wildcard */
|
||||
@ -810,9 +787,10 @@ static psa_algorithm_t psa_key_policy_algorithm_intersection(
|
||||
else
|
||||
return( 0 );
|
||||
}
|
||||
/* If none of them are wildcards, check whether we can match
|
||||
* default-length with exact-length, and return exact-length in that
|
||||
* case. */
|
||||
/* If none of them are wildcards, check whether this is a case of one
|
||||
* specifying the default length and the other a specific length. If the
|
||||
* specific length equals the default length for this key type, the
|
||||
* intersection would be the specific-length algorithm. */
|
||||
if( alg1_len == alg2_len )
|
||||
return( PSA_ALG_TRUNCATED_MAC( alg1, alg1_len ) );
|
||||
}
|
||||
@ -853,27 +831,25 @@ static int psa_key_algorithm_permits( psa_key_type_t key_type,
|
||||
( PSA_ALG_FULL_LENGTH_MAC( policy_alg ) ==
|
||||
PSA_ALG_FULL_LENGTH_MAC( requested_alg ) ) )
|
||||
{
|
||||
size_t actual_output_length;
|
||||
size_t default_output_length;
|
||||
if( PSA_SUCCESS != psa_get_mac_output_length(
|
||||
requested_alg,
|
||||
key_type,
|
||||
&actual_output_length ) )
|
||||
{
|
||||
/* Validate the combination of key type and algorithm. Since the policy
|
||||
* and requested algorithms are the same, we only need this once. */
|
||||
if( PSA_SUCCESS != psa_mac_key_can_do( policy_alg, key_type ) )
|
||||
return( 0 );
|
||||
}
|
||||
if( PSA_SUCCESS != psa_get_mac_output_length(
|
||||
PSA_ALG_FULL_LENGTH_MAC( requested_alg ),
|
||||
key_type,
|
||||
&default_output_length ) )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Get both the requested and the default output length for this
|
||||
* algorithm and key combination. None of the currently supported
|
||||
* algorithms have an output length dependent on actual key size, so
|
||||
* setting it to a bogus value is currently OK. */
|
||||
size_t requested_output_length = PSA_MAC_LENGTH(
|
||||
key_type, 0, requested_alg );
|
||||
size_t default_output_length = PSA_MAC_LENGTH(
|
||||
key_type, 0,
|
||||
PSA_ALG_FULL_LENGTH_MAC( requested_alg ) );
|
||||
|
||||
/* If the policy is default-length, only allow an algorithm with
|
||||
* a declared exact-length matching the default. */
|
||||
if( PSA_MAC_TRUNCATED_LENGTH( policy_alg ) == 0 )
|
||||
return( actual_output_length == default_output_length );
|
||||
return( requested_output_length == default_output_length );
|
||||
|
||||
/* If the requested algorithm is default-length, allow it if the policy
|
||||
* is exactly the default length. */
|
||||
@ -889,7 +865,7 @@ static int psa_key_algorithm_permits( psa_key_type_t key_type,
|
||||
if( ( policy_alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG ) != 0 )
|
||||
{
|
||||
return( PSA_MAC_TRUNCATED_LENGTH( policy_alg ) <=
|
||||
actual_output_length );
|
||||
requested_output_length );
|
||||
}
|
||||
}
|
||||
/* If policy_alg is a generic key agreement operation, then using it for
|
||||
@ -2981,7 +2957,6 @@ static psa_status_t psa_mac_setup( psa_mac_operation_t *operation,
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_key_slot_t *slot;
|
||||
size_t output_length = 0;
|
||||
psa_key_usage_t usage =
|
||||
is_sign ? PSA_KEY_USAGE_SIGN_HASH : PSA_KEY_USAGE_VERIFY_HASH;
|
||||
|
||||
@ -3002,12 +2977,15 @@ static psa_status_t psa_mac_setup( psa_mac_operation_t *operation,
|
||||
if( status != PSA_SUCCESS )
|
||||
goto exit;
|
||||
|
||||
status = psa_get_mac_output_length( alg, slot->attr.type,
|
||||
&output_length );
|
||||
/* Validate the combination of key type and algorithm */
|
||||
status = psa_mac_key_can_do( alg, slot->attr.type );
|
||||
if( status != PSA_SUCCESS )
|
||||
goto exit;
|
||||
|
||||
operation->mac_size = (uint8_t) output_length;
|
||||
/* Get the output length for the algorithm and key combination. None of the
|
||||
* currently supported algorithms have an output length dependent on actual
|
||||
* key size, so setting it to a bogus value is currently OK. */
|
||||
operation->mac_size = PSA_MAC_LENGTH( slot->attr.type, 0, alg );
|
||||
|
||||
if( operation->mac_size < 4 )
|
||||
{
|
||||
@ -3019,6 +2997,15 @@ static psa_status_t psa_mac_setup( psa_mac_operation_t *operation,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if( operation->mac_size >
|
||||
PSA_MAC_LENGTH( slot->attr.type, 0, PSA_ALG_FULL_LENGTH_MAC( alg ) ) )
|
||||
{
|
||||
/* It's impossible to "truncate" to a larger length than the full length
|
||||
* of the algorithm. */
|
||||
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_CMAC_C)
|
||||
if( PSA_ALG_FULL_LENGTH_MAC( alg ) == PSA_ALG_CMAC )
|
||||
{
|
||||
|
@ -78,9 +78,9 @@ psa_status_t mbedtls_psa_crypto_configure_entropy_sources(
|
||||
#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
|
||||
|
||||
#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C)
|
||||
psa_status_t psa_get_mac_output_length( psa_algorithm_t algorithm,
|
||||
psa_key_type_t key_type,
|
||||
size_t *length );
|
||||
psa_status_t psa_mac_key_can_do(
|
||||
psa_algorithm_t algorithm,
|
||||
psa_key_type_t key_type );
|
||||
#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_PSA_CRYPTO_C */
|
||||
|
||||
#endif /* PSA_CRYPTO_INVASIVE_H */
|
||||
|
@ -1086,7 +1086,8 @@ depends_on:MBEDTLS_AES_C:MBEDTLS_CMAC_C
|
||||
mac_setup:PSA_KEY_TYPE_AES:"000102030405060708090a0b0c0d0e0f":PSA_ALG_CMAC:PSA_SUCCESS
|
||||
|
||||
PSA MAC setup: bad algorithm (HMAC without specified hash)
|
||||
mac_setup:PSA_KEY_TYPE_HMAC:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f":PSA_ALG_HMAC(0):PSA_ERROR_INVALID_ARGUMENT
|
||||
# Either INVALID_ARGUMENT or NOT_SUPPORTED would be reasonable here
|
||||
mac_setup:PSA_KEY_TYPE_HMAC:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f":PSA_ALG_HMAC(0):PSA_ERROR_NOT_SUPPORTED
|
||||
|
||||
PSA MAC setup: bad algorithm (unsupported HMAC hash algorithm)
|
||||
depends_on:!PSA_WANT_ALG_MD2
|
||||
|
@ -160,9 +160,7 @@ void mac_algorithm_core( psa_algorithm_t alg, int classification_flags,
|
||||
TEST_EQUAL( length, PSA_MAC_LENGTH( key_type, key_bits, alg ) );
|
||||
|
||||
#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C)
|
||||
size_t output_length = 0;
|
||||
PSA_ASSERT( psa_get_mac_output_length( alg, key_type, &output_length ) );
|
||||
TEST_EQUAL( length, output_length );
|
||||
PSA_ASSERT( psa_mac_key_can_do( alg, key_type ) );
|
||||
#endif
|
||||
|
||||
exit: ;
|
||||
|
Loading…
Reference in New Issue
Block a user