mirror of
				https://github.com/cuberite/polarssl.git
				synced 2025-11-04 04:32:24 -05: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
 | 
					 | 
				
			||||||
 *     dst_nonce_len == fixed_iv_len + dynamic_iv_len
 | 
					 | 
				
			||||||
 * - If mode == SSL_RECORD_AEAD_NONCE_XOR, then
 | 
					 | 
				
			||||||
 *     dst_nonce_len == fixed_iv_len &&
 | 
					 | 
				
			||||||
 *     dynamic_iv_len < dst_nonce
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static int ssl_build_record_nonce( unsigned char *dst_nonce,
 | 
					 | 
				
			||||||
                                   size_t dst_nonce_len,
 | 
					 | 
				
			||||||
                                   unsigned char const *fixed_iv,
 | 
					 | 
				
			||||||
                                   size_t fixed_iv_len,
 | 
					 | 
				
			||||||
                                   unsigned char const *dynamic_iv,
 | 
					 | 
				
			||||||
                                   size_t dynamic_iv_len,
 | 
					 | 
				
			||||||
                                   unsigned mode )
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ((void) dst_nonce_len);
 | 
					/* Compute IV := ( fixed_iv || 0 ) XOR ( 0 || dynamic_IV )
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Concretely, this occurs in two variants:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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 void ssl_build_record_nonce( unsigned char *dst_iv,
 | 
				
			||||||
 | 
					                                    size_t dst_iv_len,
 | 
				
			||||||
 | 
					                                    unsigned char const *fixed_iv,
 | 
				
			||||||
 | 
					                                    size_t fixed_iv_len,
 | 
				
			||||||
 | 
					                                    unsigned char const *dynamic_iv,
 | 
				
			||||||
 | 
					                                    size_t dynamic_iv_len )
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* 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;
 | 
				
			||||||
    {
 | 
					    for( i = 0; i < dynamic_iv_len; i++ )
 | 
				
			||||||
        /* Nonce := Fixed IV || Dynamic IV */
 | 
					        dst_iv[i] ^= dynamic_iv[i];
 | 
				
			||||||
        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++ )
 | 
					 | 
				
			||||||
            dst_nonce[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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user