mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2024-11-23 02:55:41 +01:00
Refactor AEAD setup into a common function
There was a lot of repetition between psa_aead_encrypt and psa_aead_decrypt. Refactor the code into a new function psa_aead_setup. The new code should behave identically except that in some cases where multiple error conditions apply, the code may now return a different error code. Internally, I rearranged some of the code: * I removed a check that the key type was in CATEGORY_SYMMETRIC because it's redundant with mbedtls_cipher_info_from_psa which enumerates supported key types explicitly. * The order of some validations is different to allow the split between setup and data processing. The code now calls a more robust function psa_aead_abort in case of any error after the early stage of the setup.
This commit is contained in:
parent
d911eb7915
commit
edf9a6576d
@ -2821,6 +2821,102 @@ psa_status_t psa_set_key_lifetime( psa_key_slot_t key,
|
|||||||
/* AEAD */
|
/* AEAD */
|
||||||
/****************************************************************/
|
/****************************************************************/
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
key_slot_t *slot;
|
||||||
|
const mbedtls_cipher_info_t *cipher_info;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
#if defined(MBEDTLS_CCM_C)
|
||||||
|
mbedtls_ccm_context ccm;
|
||||||
|
#endif /* MBEDTLS_CCM_C */
|
||||||
|
#if defined(MBEDTLS_GCM_C)
|
||||||
|
mbedtls_gcm_context gcm;
|
||||||
|
#endif /* MBEDTLS_GCM_C */
|
||||||
|
} ctx;
|
||||||
|
uint8_t tag_length;
|
||||||
|
} aead_operation_t;
|
||||||
|
|
||||||
|
static void psa_aead_abort( aead_operation_t *operation,
|
||||||
|
psa_algorithm_t alg )
|
||||||
|
{
|
||||||
|
switch( alg )
|
||||||
|
{
|
||||||
|
#if defined(MBEDTLS_CCM_C)
|
||||||
|
case PSA_ALG_CCM:
|
||||||
|
mbedtls_ccm_free( &operation->ctx.ccm );
|
||||||
|
break;
|
||||||
|
#endif /* MBEDTLS_CCM_C */
|
||||||
|
#if defined(MBEDTLS_CCM_C)
|
||||||
|
case PSA_ALG_GCM:
|
||||||
|
mbedtls_gcm_free( &operation->ctx.gcm );
|
||||||
|
break;
|
||||||
|
#endif /* MBEDTLS_GCM_C */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static psa_status_t psa_aead_setup( aead_operation_t *operation,
|
||||||
|
psa_key_slot_t key,
|
||||||
|
psa_key_usage_t usage,
|
||||||
|
psa_algorithm_t alg )
|
||||||
|
{
|
||||||
|
psa_status_t status;
|
||||||
|
size_t key_bits;
|
||||||
|
mbedtls_cipher_id_t cipher_id;
|
||||||
|
|
||||||
|
status = psa_get_key_from_slot( key, &operation->slot, usage, alg );
|
||||||
|
if( status != PSA_SUCCESS )
|
||||||
|
return( status );
|
||||||
|
|
||||||
|
key_bits = psa_get_key_bits( operation->slot );
|
||||||
|
|
||||||
|
operation->cipher_info =
|
||||||
|
mbedtls_cipher_info_from_psa( alg, operation->slot->type, key_bits,
|
||||||
|
&cipher_id );
|
||||||
|
if( operation->cipher_info == NULL )
|
||||||
|
return( PSA_ERROR_NOT_SUPPORTED );
|
||||||
|
|
||||||
|
switch( alg )
|
||||||
|
{
|
||||||
|
#if defined(MBEDTLS_CCM_C)
|
||||||
|
case PSA_ALG_CCM:
|
||||||
|
operation->tag_length = 16;
|
||||||
|
if( PSA_BLOCK_CIPHER_BLOCK_SIZE( operation->slot->type ) != 16 )
|
||||||
|
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||||
|
mbedtls_ccm_init( &operation->ctx.ccm );
|
||||||
|
status = mbedtls_to_psa_error(
|
||||||
|
mbedtls_ccm_setkey( &operation->ctx.ccm, cipher_id,
|
||||||
|
operation->slot->data.raw.data,
|
||||||
|
(unsigned int) key_bits ) );
|
||||||
|
if( status != 0 )
|
||||||
|
goto cleanup;
|
||||||
|
break;
|
||||||
|
#endif /* MBEDTLS_CCM_C */
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_GCM_C)
|
||||||
|
case PSA_ALG_GCM:
|
||||||
|
operation->tag_length = 16;
|
||||||
|
if( PSA_BLOCK_CIPHER_BLOCK_SIZE( operation->slot->type ) != 16 )
|
||||||
|
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||||
|
mbedtls_gcm_init( &operation->ctx.gcm );
|
||||||
|
status = mbedtls_to_psa_error(
|
||||||
|
mbedtls_gcm_setkey( &operation->ctx.gcm, cipher_id,
|
||||||
|
operation->slot->data.raw.data,
|
||||||
|
(unsigned int) key_bits ) );
|
||||||
|
break;
|
||||||
|
#endif /* MBEDTLS_GCM_C */
|
||||||
|
|
||||||
|
default:
|
||||||
|
return( PSA_ERROR_NOT_SUPPORTED );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( PSA_SUCCESS );
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
psa_aead_abort( operation, alg );
|
||||||
|
return( status );
|
||||||
|
}
|
||||||
|
|
||||||
psa_status_t psa_aead_encrypt( psa_key_slot_t key,
|
psa_status_t psa_aead_encrypt( psa_key_slot_t key,
|
||||||
psa_algorithm_t alg,
|
psa_algorithm_t alg,
|
||||||
const uint8_t *nonce,
|
const uint8_t *nonce,
|
||||||
@ -2833,113 +2929,60 @@ psa_status_t psa_aead_encrypt( psa_key_slot_t key,
|
|||||||
size_t ciphertext_size,
|
size_t ciphertext_size,
|
||||||
size_t *ciphertext_length )
|
size_t *ciphertext_length )
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
psa_status_t status;
|
psa_status_t status;
|
||||||
key_slot_t *slot;
|
aead_operation_t operation;
|
||||||
size_t key_bits;
|
|
||||||
uint8_t *tag;
|
uint8_t *tag;
|
||||||
size_t tag_length;
|
|
||||||
mbedtls_cipher_id_t cipher_id;
|
|
||||||
const mbedtls_cipher_info_t *cipher_info = NULL;
|
|
||||||
|
|
||||||
*ciphertext_length = 0;
|
*ciphertext_length = 0;
|
||||||
|
|
||||||
status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_ENCRYPT, alg );
|
status = psa_aead_setup( &operation, key, PSA_KEY_USAGE_ENCRYPT, alg );
|
||||||
if( status != PSA_SUCCESS )
|
if( status != PSA_SUCCESS )
|
||||||
return( status );
|
return( status );
|
||||||
key_bits = psa_get_key_bits( slot );
|
|
||||||
|
|
||||||
cipher_info = mbedtls_cipher_info_from_psa( alg, slot->type,
|
/* For all currently supported modes, the tag is at the end of the
|
||||||
key_bits, &cipher_id );
|
* ciphertext. */
|
||||||
if( cipher_info == NULL )
|
if( ciphertext_size < ( plaintext_length + operation.tag_length ) )
|
||||||
return( PSA_ERROR_NOT_SUPPORTED );
|
{
|
||||||
|
status = PSA_ERROR_BUFFER_TOO_SMALL;
|
||||||
if( ( slot->type & PSA_KEY_TYPE_CATEGORY_MASK ) !=
|
goto exit;
|
||||||
PSA_KEY_TYPE_CATEGORY_SYMMETRIC )
|
}
|
||||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
tag = ciphertext + plaintext_length;
|
||||||
|
|
||||||
if( alg == PSA_ALG_GCM )
|
if( alg == PSA_ALG_GCM )
|
||||||
{
|
{
|
||||||
mbedtls_gcm_context gcm;
|
status = mbedtls_to_psa_error(
|
||||||
tag_length = 16;
|
mbedtls_gcm_crypt_and_tag( &operation.ctx.gcm,
|
||||||
|
MBEDTLS_GCM_ENCRYPT,
|
||||||
if( PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->type ) != 16 )
|
plaintext_length,
|
||||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
nonce, nonce_length,
|
||||||
|
additional_data, additional_data_length,
|
||||||
//make sure we have place to hold the tag in the ciphertext buffer
|
plaintext, ciphertext,
|
||||||
if( ciphertext_size < ( plaintext_length + tag_length ) )
|
operation.tag_length, tag ) );
|
||||||
return( PSA_ERROR_BUFFER_TOO_SMALL );
|
|
||||||
|
|
||||||
//update the tag pointer to point to the end of the ciphertext_length
|
|
||||||
tag = ciphertext + plaintext_length;
|
|
||||||
|
|
||||||
mbedtls_gcm_init( &gcm );
|
|
||||||
ret = mbedtls_gcm_setkey( &gcm, cipher_id,
|
|
||||||
slot->data.raw.data,
|
|
||||||
(unsigned int) key_bits );
|
|
||||||
if( ret != 0 )
|
|
||||||
{
|
|
||||||
mbedtls_gcm_free( &gcm );
|
|
||||||
return( mbedtls_to_psa_error( ret ) );
|
|
||||||
}
|
|
||||||
ret = mbedtls_gcm_crypt_and_tag( &gcm, MBEDTLS_GCM_ENCRYPT,
|
|
||||||
plaintext_length, nonce,
|
|
||||||
nonce_length, additional_data,
|
|
||||||
additional_data_length, plaintext,
|
|
||||||
ciphertext, tag_length, tag );
|
|
||||||
mbedtls_gcm_free( &gcm );
|
|
||||||
}
|
}
|
||||||
else if( alg == PSA_ALG_CCM )
|
else if( alg == PSA_ALG_CCM )
|
||||||
{
|
{
|
||||||
mbedtls_ccm_context ccm;
|
status = mbedtls_to_psa_error(
|
||||||
tag_length = 16;
|
mbedtls_ccm_encrypt_and_tag( &operation.ctx.ccm,
|
||||||
|
plaintext_length,
|
||||||
if( PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->type ) != 16 )
|
nonce, nonce_length,
|
||||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
additional_data,
|
||||||
|
additional_data_length,
|
||||||
if( nonce_length < 7 || nonce_length > 13 )
|
plaintext, ciphertext,
|
||||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
tag, operation.tag_length ) );
|
||||||
|
|
||||||
//make sure we have place to hold the tag in the ciphertext buffer
|
|
||||||
if( ciphertext_size < ( plaintext_length + tag_length ) )
|
|
||||||
return( PSA_ERROR_BUFFER_TOO_SMALL );
|
|
||||||
|
|
||||||
//update the tag pointer to point to the end of the ciphertext_length
|
|
||||||
tag = ciphertext + plaintext_length;
|
|
||||||
|
|
||||||
mbedtls_ccm_init( &ccm );
|
|
||||||
ret = mbedtls_ccm_setkey( &ccm, cipher_id,
|
|
||||||
slot->data.raw.data,
|
|
||||||
(unsigned int) key_bits );
|
|
||||||
if( ret != 0 )
|
|
||||||
{
|
|
||||||
mbedtls_ccm_free( &ccm );
|
|
||||||
return( mbedtls_to_psa_error( ret ) );
|
|
||||||
}
|
|
||||||
ret = mbedtls_ccm_encrypt_and_tag( &ccm, plaintext_length,
|
|
||||||
nonce, nonce_length,
|
|
||||||
additional_data,
|
|
||||||
additional_data_length,
|
|
||||||
plaintext, ciphertext,
|
|
||||||
tag, tag_length );
|
|
||||||
mbedtls_ccm_free( &ccm );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return( PSA_ERROR_NOT_SUPPORTED );
|
return( PSA_ERROR_NOT_SUPPORTED );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ret != 0 )
|
if( status != PSA_SUCCESS && ciphertext_size != 0 )
|
||||||
{
|
memset( ciphertext, 0, ciphertext_size );
|
||||||
/* If ciphertext_size is 0 then ciphertext may be NULL and then the
|
|
||||||
* call to memset would have undefined behavior. */
|
|
||||||
if( ciphertext_size != 0 )
|
|
||||||
memset( ciphertext, 0, ciphertext_size );
|
|
||||||
return( mbedtls_to_psa_error( ret ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
*ciphertext_length = plaintext_length + tag_length;
|
exit:
|
||||||
return( PSA_SUCCESS );
|
psa_aead_abort( &operation, alg );
|
||||||
|
if( status == PSA_SUCCESS )
|
||||||
|
*ciphertext_length = plaintext_length + operation.tag_length;
|
||||||
|
return( status );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Locate the tag in a ciphertext buffer containing the encrypted data
|
/* Locate the tag in a ciphertext buffer containing the encrypted data
|
||||||
@ -2975,108 +3018,63 @@ psa_status_t psa_aead_decrypt( psa_key_slot_t key,
|
|||||||
size_t plaintext_size,
|
size_t plaintext_size,
|
||||||
size_t *plaintext_length )
|
size_t *plaintext_length )
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
psa_status_t status;
|
psa_status_t status;
|
||||||
key_slot_t *slot;
|
aead_operation_t operation;
|
||||||
size_t key_bits;
|
const uint8_t *tag = NULL;
|
||||||
const uint8_t *tag;
|
|
||||||
size_t tag_length;
|
|
||||||
mbedtls_cipher_id_t cipher_id;
|
|
||||||
const mbedtls_cipher_info_t *cipher_info = NULL;
|
|
||||||
|
|
||||||
*plaintext_length = 0;
|
*plaintext_length = 0;
|
||||||
|
|
||||||
status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_DECRYPT, alg );
|
status = psa_aead_setup( &operation, key, PSA_KEY_USAGE_DECRYPT, alg );
|
||||||
if( status != PSA_SUCCESS )
|
if( status != PSA_SUCCESS )
|
||||||
return( status );
|
return( status );
|
||||||
key_bits = psa_get_key_bits( slot );
|
|
||||||
|
|
||||||
cipher_info = mbedtls_cipher_info_from_psa( alg, slot->type,
|
|
||||||
key_bits, &cipher_id );
|
|
||||||
if( cipher_info == NULL )
|
|
||||||
return( PSA_ERROR_NOT_SUPPORTED );
|
|
||||||
|
|
||||||
if( ( slot->type & PSA_KEY_TYPE_CATEGORY_MASK ) !=
|
|
||||||
PSA_KEY_TYPE_CATEGORY_SYMMETRIC )
|
|
||||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
|
||||||
|
|
||||||
if( alg == PSA_ALG_GCM )
|
if( alg == PSA_ALG_GCM )
|
||||||
{
|
{
|
||||||
mbedtls_gcm_context gcm;
|
status = psa_aead_unpadded_locate_tag( operation.tag_length,
|
||||||
|
|
||||||
tag_length = 16;
|
|
||||||
status = psa_aead_unpadded_locate_tag( tag_length,
|
|
||||||
ciphertext, ciphertext_length,
|
ciphertext, ciphertext_length,
|
||||||
plaintext_size, &tag );
|
plaintext_size, &tag );
|
||||||
if( status != PSA_SUCCESS )
|
if( status != PSA_SUCCESS )
|
||||||
return( status );
|
goto exit;
|
||||||
|
|
||||||
mbedtls_gcm_init( &gcm );
|
status = mbedtls_to_psa_error(
|
||||||
ret = mbedtls_gcm_setkey( &gcm, cipher_id,
|
mbedtls_gcm_auth_decrypt( &operation.ctx.gcm,
|
||||||
slot->data.raw.data,
|
ciphertext_length - operation.tag_length,
|
||||||
(unsigned int) key_bits );
|
nonce, nonce_length,
|
||||||
if( ret != 0 )
|
additional_data,
|
||||||
{
|
additional_data_length,
|
||||||
mbedtls_gcm_free( &gcm );
|
tag, operation.tag_length,
|
||||||
return( mbedtls_to_psa_error( ret ) );
|
ciphertext, plaintext ) );
|
||||||
}
|
|
||||||
|
|
||||||
ret = mbedtls_gcm_auth_decrypt( &gcm,
|
|
||||||
ciphertext_length - tag_length,
|
|
||||||
nonce, nonce_length,
|
|
||||||
additional_data,
|
|
||||||
additional_data_length,
|
|
||||||
tag, tag_length,
|
|
||||||
ciphertext, plaintext );
|
|
||||||
mbedtls_gcm_free( &gcm );
|
|
||||||
}
|
}
|
||||||
else if( alg == PSA_ALG_CCM )
|
else if( alg == PSA_ALG_CCM )
|
||||||
{
|
{
|
||||||
mbedtls_ccm_context ccm;
|
status = psa_aead_unpadded_locate_tag( operation.tag_length,
|
||||||
|
|
||||||
if( nonce_length < 7 || nonce_length > 13 )
|
|
||||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
|
||||||
|
|
||||||
tag_length = 16;
|
|
||||||
status = psa_aead_unpadded_locate_tag( tag_length,
|
|
||||||
ciphertext, ciphertext_length,
|
ciphertext, ciphertext_length,
|
||||||
plaintext_size, &tag );
|
plaintext_size, &tag );
|
||||||
if( status != PSA_SUCCESS )
|
if( status != PSA_SUCCESS )
|
||||||
return( status );
|
goto exit;
|
||||||
|
|
||||||
mbedtls_ccm_init( &ccm );
|
status = mbedtls_to_psa_error(
|
||||||
ret = mbedtls_ccm_setkey( &ccm, cipher_id,
|
mbedtls_ccm_auth_decrypt( &operation.ctx.ccm,
|
||||||
slot->data.raw.data,
|
ciphertext_length - operation.tag_length,
|
||||||
(unsigned int) key_bits );
|
nonce, nonce_length,
|
||||||
if( ret != 0 )
|
additional_data,
|
||||||
{
|
additional_data_length,
|
||||||
mbedtls_ccm_free( &ccm );
|
ciphertext, plaintext,
|
||||||
return( mbedtls_to_psa_error( ret ) );
|
tag, operation.tag_length ) );
|
||||||
}
|
|
||||||
ret = mbedtls_ccm_auth_decrypt( &ccm, ciphertext_length - tag_length,
|
|
||||||
nonce, nonce_length,
|
|
||||||
additional_data,
|
|
||||||
additional_data_length,
|
|
||||||
ciphertext, plaintext,
|
|
||||||
tag, tag_length );
|
|
||||||
mbedtls_ccm_free( &ccm );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return( PSA_ERROR_NOT_SUPPORTED );
|
return( PSA_ERROR_NOT_SUPPORTED );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ret != 0 )
|
if( status != PSA_SUCCESS && plaintext_size != 0 )
|
||||||
{
|
memset( plaintext, 0, plaintext_size );
|
||||||
/* If plaintext_size is 0 then plaintext may be NULL and then the
|
|
||||||
* call to memset has undefined behavior. */
|
|
||||||
if( plaintext_size != 0 )
|
|
||||||
memset( plaintext, 0, plaintext_size );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
*plaintext_length = ciphertext_length - tag_length;
|
|
||||||
|
|
||||||
return( mbedtls_to_psa_error( ret ) );
|
exit:
|
||||||
|
psa_aead_abort( &operation, alg );
|
||||||
|
if( status == PSA_SUCCESS )
|
||||||
|
*plaintext_length = ciphertext_length - operation.tag_length;
|
||||||
|
return( status );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user