mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2025-02-24 10:46:54 +00:00
Simplify AEAD nonce derivation
This commit simplifies nonce derivation for AEAD based record protection routines in the following way. So far, code distinguished between the cases of GCM+CCM and ChachaPoly: - In the case of GCM+CCM, the AEAD nonce is the concatentation of a 4-byte Fixed IV and a dynamically chosen 8-byte IV which is prepended to the record. In Mbed TLS, this is always chosen to be the record sequence number, but it need not to. - In the case of ChaChaPoly, the AEAD nonce is derived as `( 12-byte Fixed IV ) XOR ( 0 || 8-byte dynamic IV == record seq nr )` and the dynamically chosen IV is no longer prepended to the record. This commit removes this distinction by always computing the record nonce via the formula `IV == ( Fixed IV || 0 ) XOR ( 0 || Dynamic IV )` The ChaChaPoly case is recovered in case `Len(Fixed IV) == Len(IV)`, and GCM+CCM is recovered when `Len(IV) == Len(Fixed IV) + Len(Dynamic IV)`. Moreover, a getter stub `ssl_transform_aead_dynamic_iv_is_explicit()` is introduced which infers from a transform whether the dynamically chosen part of the IV is explicit, which in the current implementation of `mbedtls_ssl_transform` can be derived from the helper field `mbedtls_ssl_transform::fixed_ivlen`. Signed-off-by: Hanno Becker <hanno.becker@arm.com>
This commit is contained in:
parent
df8be226ba
commit
17263803aa
|
@ -536,76 +536,39 @@ static void ssl_mac( mbedtls_md_context_t *md_ctx,
|
||||||
}
|
}
|
||||||
#endif /* MBEDTLS_SSL_PROTO_SSL3 */
|
#endif /* MBEDTLS_SSL_PROTO_SSL3 */
|
||||||
|
|
||||||
#define SSL_RECORD_AEAD_NONCE_UNKNOWN 0u
|
static int ssl_transform_aead_dynamic_iv_is_explicit(
|
||||||
#define SSL_RECORD_AEAD_NONCE_CONCAT 1u
|
mbedtls_ssl_transform const *transform )
|
||||||
#define SSL_RECORD_AEAD_NONCE_XOR 2u
|
|
||||||
|
|
||||||
static int ssl_transform_get_nonce_mode( mbedtls_ssl_transform const *transform )
|
|
||||||
{
|
{
|
||||||
#if defined(MBEDTLS_CHACHAPOLY_C)
|
return( transform->ivlen != transform->fixed_ivlen );
|
||||||
if( transform->ivlen == 12 && transform->fixed_ivlen == 12 )
|
|
||||||
{
|
|
||||||
return( SSL_RECORD_AEAD_NONCE_XOR );
|
|
||||||
}
|
|
||||||
#endif /* MBEDTLS_CHACHAPOLY_C */
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C)
|
|
||||||
if( transform->ivlen == 12 && transform->fixed_ivlen == 4 )
|
|
||||||
{
|
|
||||||
return( SSL_RECORD_AEAD_NONCE_CONCAT );
|
|
||||||
}
|
|
||||||
#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */
|
|
||||||
|
|
||||||
return( SSL_RECORD_AEAD_NONCE_UNKNOWN );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Preconditions:
|
|
||||||
* - If mode == SSL_RECORD_AEAD_NONCE_CONCAT, then
|
/* Compute IV := ( fixed_iv || 0 ) XOR ( 0 || dynamic_IV )
|
||||||
* dst_nonce_len == fixed_iv_len + dynamic_iv_len
|
*
|
||||||
* - If mode == SSL_RECORD_AEAD_NONCE_XOR, then
|
* Concretely, this occurs in two variants:
|
||||||
* dst_nonce_len == fixed_iv_len &&
|
*
|
||||||
* dynamic_iv_len < dst_nonce
|
* a) Fixed and dynamic IV lengths add up to total IV length, giving
|
||||||
|
* IV = fixed_iv || dynamic_iv
|
||||||
|
*
|
||||||
|
* b) Fixed IV lengths matches total IV length, giving
|
||||||
|
* IV = fixed_iv XOR ( 0 || dynamic_iv )
|
||||||
*/
|
*/
|
||||||
static int ssl_build_record_nonce( unsigned char *dst_nonce,
|
static void ssl_build_record_nonce( unsigned char *dst_iv,
|
||||||
size_t dst_nonce_len,
|
size_t dst_iv_len,
|
||||||
unsigned char const *fixed_iv,
|
unsigned char const *fixed_iv,
|
||||||
size_t fixed_iv_len,
|
size_t fixed_iv_len,
|
||||||
unsigned char const *dynamic_iv,
|
unsigned char const *dynamic_iv,
|
||||||
size_t dynamic_iv_len,
|
size_t dynamic_iv_len )
|
||||||
unsigned mode )
|
|
||||||
{
|
{
|
||||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
size_t i;
|
||||||
|
|
||||||
((void) dst_nonce_len);
|
|
||||||
|
|
||||||
/* Start with Fixed IV || 0 */
|
/* Start with Fixed IV || 0 */
|
||||||
memcpy( dst_nonce, fixed_iv, fixed_iv_len );
|
memset( dst_iv, 0, dst_iv_len );
|
||||||
dst_nonce += fixed_iv_len;
|
memcpy( dst_iv, fixed_iv, fixed_iv_len );
|
||||||
|
|
||||||
if( mode == SSL_RECORD_AEAD_NONCE_CONCAT )
|
dst_iv += dst_iv_len - dynamic_iv_len;
|
||||||
{
|
|
||||||
/* Nonce := Fixed IV || Dynamic IV */
|
|
||||||
memcpy( dst_nonce, dynamic_iv, dynamic_iv_len );
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
else if( mode == SSL_RECORD_AEAD_NONCE_XOR )
|
|
||||||
{
|
|
||||||
/* Nonce := Fixed IV XOR ( 0 || Dynamic IV ) */
|
|
||||||
unsigned char i;
|
|
||||||
|
|
||||||
/* This is safe by the second precondition above. */
|
|
||||||
dst_nonce -= dynamic_iv_len;
|
|
||||||
for( i = 0; i < dynamic_iv_len; i++ )
|
for( i = 0; i < dynamic_iv_len; i++ )
|
||||||
dst_nonce[i] ^= dynamic_iv[i];
|
dst_iv[i] ^= dynamic_iv[i];
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return( ret );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
|
int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
|
||||||
|
@ -833,11 +796,8 @@ int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
|
||||||
unsigned char iv[12];
|
unsigned char iv[12];
|
||||||
unsigned char *dynamic_iv;
|
unsigned char *dynamic_iv;
|
||||||
size_t dynamic_iv_len;
|
size_t dynamic_iv_len;
|
||||||
|
int dynamic_iv_is_explicit =
|
||||||
unsigned const nonce_mode
|
ssl_transform_aead_dynamic_iv_is_explicit( transform );
|
||||||
= ssl_transform_get_nonce_mode( transform );
|
|
||||||
unsigned const dynamic_iv_is_explicit
|
|
||||||
= nonce_mode == SSL_RECORD_AEAD_NONCE_CONCAT;
|
|
||||||
|
|
||||||
/* Check that there's space for the authentication tag. */
|
/* Check that there's space for the authentication tag. */
|
||||||
if( post_avail < transform->taglen )
|
if( post_avail < transform->taglen )
|
||||||
|
@ -861,14 +821,11 @@ int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
|
||||||
dynamic_iv = rec->ctr;
|
dynamic_iv = rec->ctr;
|
||||||
dynamic_iv_len = sizeof( rec->ctr );
|
dynamic_iv_len = sizeof( rec->ctr );
|
||||||
|
|
||||||
ret = ssl_build_record_nonce( iv, sizeof( iv ),
|
ssl_build_record_nonce( iv, sizeof( iv ),
|
||||||
transform->iv_enc,
|
transform->iv_enc,
|
||||||
transform->fixed_ivlen,
|
transform->fixed_ivlen,
|
||||||
dynamic_iv,
|
dynamic_iv,
|
||||||
dynamic_iv_len,
|
dynamic_iv_len );
|
||||||
nonce_mode );
|
|
||||||
if( ret != 0 )
|
|
||||||
return( ret );
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Build additional data for AEAD encryption.
|
* Build additional data for AEAD encryption.
|
||||||
|
@ -911,7 +868,7 @@ int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
|
||||||
/*
|
/*
|
||||||
* Prefix record content with dynamic IV in case it is explicit.
|
* Prefix record content with dynamic IV in case it is explicit.
|
||||||
*/
|
*/
|
||||||
if( dynamic_iv_is_explicit == 1 )
|
if( dynamic_iv_is_explicit )
|
||||||
{
|
{
|
||||||
if( rec->data_offset < dynamic_iv_len )
|
if( rec->data_offset < dynamic_iv_len )
|
||||||
{
|
{
|
||||||
|
@ -1160,7 +1117,6 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
|
||||||
mode == MBEDTLS_MODE_CHACHAPOLY )
|
mode == MBEDTLS_MODE_CHACHAPOLY )
|
||||||
{
|
{
|
||||||
unsigned char iv[12];
|
unsigned char iv[12];
|
||||||
unsigned const nonce_mode = ssl_transform_get_nonce_mode( transform );
|
|
||||||
unsigned char *dynamic_iv;
|
unsigned char *dynamic_iv;
|
||||||
size_t dynamic_iv_len;
|
size_t dynamic_iv_len;
|
||||||
|
|
||||||
|
@ -1173,11 +1129,7 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
|
||||||
* agree with the record sequence number.
|
* agree with the record sequence number.
|
||||||
*/
|
*/
|
||||||
dynamic_iv_len = sizeof( rec->ctr );
|
dynamic_iv_len = sizeof( rec->ctr );
|
||||||
if( nonce_mode == SSL_RECORD_AEAD_NONCE_XOR )
|
if( ssl_transform_aead_dynamic_iv_is_explicit( transform ) == 1 )
|
||||||
{
|
|
||||||
dynamic_iv = rec->ctr;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if( rec->data_len < dynamic_iv_len )
|
if( rec->data_len < dynamic_iv_len )
|
||||||
{
|
{
|
||||||
|
@ -1192,6 +1144,10 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
|
||||||
rec->data_offset += dynamic_iv_len;
|
rec->data_offset += dynamic_iv_len;
|
||||||
rec->data_len -= dynamic_iv_len;
|
rec->data_len -= dynamic_iv_len;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dynamic_iv = rec->ctr;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check that there's space for the authentication tag. */
|
/* Check that there's space for the authentication tag. */
|
||||||
if( rec->data_len < transform->taglen )
|
if( rec->data_len < transform->taglen )
|
||||||
|
@ -1204,14 +1160,11 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
|
||||||
/*
|
/*
|
||||||
* Prepare nonce from dynamic and static parts.
|
* Prepare nonce from dynamic and static parts.
|
||||||
*/
|
*/
|
||||||
ret = ssl_build_record_nonce( iv, sizeof( iv ),
|
ssl_build_record_nonce( iv, sizeof( iv ),
|
||||||
transform->iv_dec,
|
transform->iv_dec,
|
||||||
transform->fixed_ivlen,
|
transform->fixed_ivlen,
|
||||||
dynamic_iv,
|
dynamic_iv,
|
||||||
dynamic_iv_len,
|
dynamic_iv_len );
|
||||||
nonce_mode );
|
|
||||||
if( ret != 0 )
|
|
||||||
return( ret );
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Build additional data for AEAD encryption.
|
* Build additional data for AEAD encryption.
|
||||||
|
|
Loading…
Reference in a new issue