Merge pull request #4248 from hanno-arm/tls13_populate_transform
Fix and test compliance of TLS 1.3 record protection
This commit is contained in:
commit
2aec149e13
8 changed files with 399 additions and 50 deletions
|
@ -740,7 +740,8 @@ struct mbedtls_ssl_transform
|
|||
|
||||
#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
|
||||
/* We need the Hello random bytes in order to re-derive keys from the
|
||||
* Master Secret and other session info, see ssl_populate_transform() */
|
||||
* Master Secret and other session info,
|
||||
* see ssl_tls12_populate_transform() */
|
||||
unsigned char randbytes[64]; /*!< ServerHello.random+ClientHello.random */
|
||||
#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
|
||||
};
|
||||
|
|
|
@ -384,7 +384,8 @@ static int ssl_parse_inner_plaintext( unsigned char const *content,
|
|||
static void ssl_extract_add_data_from_record( unsigned char* add_data,
|
||||
size_t *add_data_len,
|
||||
mbedtls_record *rec,
|
||||
unsigned minor_ver )
|
||||
unsigned minor_ver,
|
||||
size_t taglen )
|
||||
{
|
||||
/* Quoting RFC 5246 (TLS 1.2):
|
||||
*
|
||||
|
@ -403,15 +404,37 @@ static void ssl_extract_add_data_from_record( unsigned char* add_data,
|
|||
*
|
||||
* For TLS 1.3, the record sequence number is dropped from the AAD
|
||||
* and encoded within the nonce of the AEAD operation instead.
|
||||
* Moreover, the additional data involves the length of the TLS
|
||||
* ciphertext, not the TLS plaintext as in earlier versions.
|
||||
* Quoting RFC 8446 (TLS 1.3):
|
||||
*
|
||||
* additional_data = TLSCiphertext.opaque_type ||
|
||||
* TLSCiphertext.legacy_record_version ||
|
||||
* TLSCiphertext.length
|
||||
*
|
||||
* We pass the tag length to this function in order to compute the
|
||||
* ciphertext length from the inner plaintext length rec->data_len via
|
||||
*
|
||||
* TLSCiphertext.length = TLSInnerPlaintext.length + taglen.
|
||||
*
|
||||
*/
|
||||
|
||||
unsigned char *cur = add_data;
|
||||
size_t ad_len_field = rec->data_len;
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
|
||||
if( minor_ver != MBEDTLS_SSL_MINOR_VERSION_4 )
|
||||
if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 )
|
||||
{
|
||||
/* In TLS 1.3, the AAD contains the length of the TLSCiphertext,
|
||||
* which differs from the length of the TLSInnerPlaintext
|
||||
* by the length of the authentication tag. */
|
||||
ad_len_field += taglen;
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
|
||||
{
|
||||
((void) minor_ver);
|
||||
((void) taglen);
|
||||
memcpy( cur, rec->ctr, sizeof( rec->ctr ) );
|
||||
cur += sizeof( rec->ctr );
|
||||
}
|
||||
|
@ -431,15 +454,15 @@ static void ssl_extract_add_data_from_record( unsigned char* add_data,
|
|||
*cur = rec->cid_len;
|
||||
cur++;
|
||||
|
||||
cur[0] = ( rec->data_len >> 8 ) & 0xFF;
|
||||
cur[1] = ( rec->data_len >> 0 ) & 0xFF;
|
||||
cur[0] = ( ad_len_field >> 8 ) & 0xFF;
|
||||
cur[1] = ( ad_len_field >> 0 ) & 0xFF;
|
||||
cur += 2;
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
|
||||
{
|
||||
cur[0] = ( rec->data_len >> 8 ) & 0xFF;
|
||||
cur[1] = ( rec->data_len >> 0 ) & 0xFF;
|
||||
cur[0] = ( ad_len_field >> 8 ) & 0xFF;
|
||||
cur[1] = ( ad_len_field >> 0 ) & 0xFF;
|
||||
cur += 2;
|
||||
}
|
||||
|
||||
|
@ -646,7 +669,8 @@ int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
|
|||
unsigned char mac[MBEDTLS_SSL_MAC_ADD];
|
||||
|
||||
ssl_extract_add_data_from_record( add_data, &add_data_len, rec,
|
||||
transform->minor_ver );
|
||||
transform->minor_ver,
|
||||
transform->taglen );
|
||||
|
||||
mbedtls_md_hmac_update( &transform->md_ctx_enc, add_data,
|
||||
add_data_len );
|
||||
|
@ -743,7 +767,8 @@ int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
|
|||
* This depends on the TLS version.
|
||||
*/
|
||||
ssl_extract_add_data_from_record( add_data, &add_data_len, rec,
|
||||
transform->minor_ver );
|
||||
transform->minor_ver,
|
||||
transform->taglen );
|
||||
|
||||
MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (internal)",
|
||||
iv, transform->ivlen );
|
||||
|
@ -897,7 +922,8 @@ int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
|
|||
}
|
||||
|
||||
ssl_extract_add_data_from_record( add_data, &add_data_len,
|
||||
rec, transform->minor_ver );
|
||||
rec, transform->minor_ver,
|
||||
transform->taglen );
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) );
|
||||
MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data,
|
||||
|
@ -1304,7 +1330,8 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
|
|||
* This depends on the TLS version.
|
||||
*/
|
||||
ssl_extract_add_data_from_record( add_data, &add_data_len, rec,
|
||||
transform->minor_ver );
|
||||
transform->minor_ver,
|
||||
transform->taglen );
|
||||
MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD",
|
||||
add_data, add_data_len );
|
||||
|
||||
|
@ -1414,7 +1441,8 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
|
|||
* Further, we still know that data_len > minlen */
|
||||
rec->data_len -= transform->maclen;
|
||||
ssl_extract_add_data_from_record( add_data, &add_data_len, rec,
|
||||
transform->minor_ver );
|
||||
transform->minor_ver,
|
||||
transform->taglen );
|
||||
|
||||
/* Calculate expected MAC. */
|
||||
MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data,
|
||||
|
@ -1606,7 +1634,8 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
|
|||
*/
|
||||
rec->data_len -= transform->maclen;
|
||||
ssl_extract_add_data_from_record( add_data, &add_data_len, rec,
|
||||
transform->minor_ver );
|
||||
transform->minor_ver,
|
||||
transform->taglen );
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
||||
/*
|
||||
|
|
|
@ -664,14 +664,14 @@ typedef int ssl_tls_prf_t(const unsigned char *, size_t, const char *,
|
|||
* - MBEDTLS_SSL_EXPORT_KEYS: ssl->conf->{f,p}_export_keys
|
||||
* - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg
|
||||
*/
|
||||
static int ssl_populate_transform( mbedtls_ssl_transform *transform,
|
||||
static int ssl_tls12_populate_transform( mbedtls_ssl_transform *transform,
|
||||
int ciphersuite,
|
||||
const unsigned char master[48],
|
||||
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
|
||||
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
|
||||
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) && \
|
||||
defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
|
||||
int encrypt_then_mac,
|
||||
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
|
||||
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
|
||||
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC &&
|
||||
MBEDTLS_SSL_SOME_SUITES_USE_MAC */
|
||||
ssl_tls_prf_t tls_prf,
|
||||
const unsigned char randbytes[64],
|
||||
int minor_ver,
|
||||
|
@ -713,6 +713,15 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform,
|
|||
memcpy( transform->randbytes, randbytes, sizeof( transform->randbytes ) );
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
|
||||
if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 )
|
||||
{
|
||||
/* At the moment, we keep TLS <= 1.2 and TLS 1.3 transform
|
||||
* generation separate. This should never happen. */
|
||||
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
|
||||
|
||||
/*
|
||||
* Get various info structures
|
||||
*/
|
||||
|
@ -805,19 +814,10 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform,
|
|||
* sequence number).
|
||||
*/
|
||||
transform->ivlen = 12;
|
||||
#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
|
||||
if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 )
|
||||
{
|
||||
if( cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY )
|
||||
transform->fixed_ivlen = 12;
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
|
||||
{
|
||||
if( cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY )
|
||||
transform->fixed_ivlen = 12;
|
||||
else
|
||||
transform->fixed_ivlen = 4;
|
||||
}
|
||||
transform->fixed_ivlen = 4;
|
||||
|
||||
/* Minimum length of encrypted record */
|
||||
explicit_ivlen = transform->ivlen - transform->fixed_ivlen;
|
||||
|
@ -1327,22 +1327,22 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl )
|
|||
}
|
||||
|
||||
/* Populate transform structure */
|
||||
ret = ssl_populate_transform( ssl->transform_negotiate,
|
||||
ssl->session_negotiate->ciphersuite,
|
||||
ssl->session_negotiate->master,
|
||||
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
|
||||
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
|
||||
ssl->session_negotiate->encrypt_then_mac,
|
||||
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
|
||||
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
|
||||
ssl->handshake->tls_prf,
|
||||
ssl->handshake->randbytes,
|
||||
ssl->minor_ver,
|
||||
ssl->conf->endpoint,
|
||||
ssl );
|
||||
ret = ssl_tls12_populate_transform( ssl->transform_negotiate,
|
||||
ssl->session_negotiate->ciphersuite,
|
||||
ssl->session_negotiate->master,
|
||||
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) && \
|
||||
defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
|
||||
ssl->session_negotiate->encrypt_then_mac,
|
||||
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC &&
|
||||
MBEDTLS_SSL_SOME_SUITES_USE_MAC */
|
||||
ssl->handshake->tls_prf,
|
||||
ssl->handshake->randbytes,
|
||||
ssl->minor_ver,
|
||||
ssl->conf->endpoint,
|
||||
ssl );
|
||||
if( ret != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_populate_transform", ret );
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls12_populate_transform", ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
|
@ -5923,14 +5923,14 @@ static int ssl_context_load( mbedtls_ssl_context *ssl,
|
|||
if( (size_t)( end - p ) < sizeof( ssl->transform->randbytes ) )
|
||||
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
||||
|
||||
ret = ssl_populate_transform( ssl->transform,
|
||||
ret = ssl_tls12_populate_transform( ssl->transform,
|
||||
ssl->session->ciphersuite,
|
||||
ssl->session->master,
|
||||
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
|
||||
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
|
||||
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) && \
|
||||
defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
|
||||
ssl->session->encrypt_then_mac,
|
||||
#endif
|
||||
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
|
||||
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC &&
|
||||
MBEDTLS_SSL_SOME_SUITES_USE_MAC */
|
||||
ssl_tls12prf_from_cs( ssl->session->ciphersuite ),
|
||||
p, /* currently pointing to randbytes */
|
||||
MBEDTLS_SSL_MINOR_VERSION_3, /* (D)TLS 1.2 is forced */
|
||||
|
|
|
@ -699,4 +699,125 @@ exit:
|
|||
return( ret );
|
||||
}
|
||||
|
||||
int mbedtls_ssl_tls13_populate_transform( mbedtls_ssl_transform *transform,
|
||||
int endpoint,
|
||||
int ciphersuite,
|
||||
mbedtls_ssl_key_set const *traffic_keys,
|
||||
mbedtls_ssl_context *ssl /* DEBUG ONLY */ )
|
||||
{
|
||||
int ret;
|
||||
mbedtls_cipher_info_t const *cipher_info;
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
|
||||
unsigned char const *key_enc;
|
||||
unsigned char const *iv_enc;
|
||||
unsigned char const *key_dec;
|
||||
unsigned char const *iv_dec;
|
||||
|
||||
#if !defined(MBEDTLS_DEBUG_C)
|
||||
ssl = NULL; /* make sure we don't use it except for those cases */
|
||||
(void) ssl;
|
||||
#endif
|
||||
|
||||
ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuite );
|
||||
if( ciphersuite_info == NULL )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %d not found",
|
||||
ciphersuite ) );
|
||||
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher );
|
||||
if( cipher_info == NULL )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher info for %u not found",
|
||||
ciphersuite_info->cipher ) );
|
||||
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup cipher contexts in target transform
|
||||
*/
|
||||
|
||||
if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_enc,
|
||||
cipher_info ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_dec,
|
||||
cipher_info ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_SRV_C)
|
||||
if( endpoint == MBEDTLS_SSL_IS_SERVER )
|
||||
{
|
||||
key_enc = traffic_keys->server_write_key;
|
||||
key_dec = traffic_keys->client_write_key;
|
||||
iv_enc = traffic_keys->server_write_iv;
|
||||
iv_dec = traffic_keys->client_write_iv;
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_SSL_SRV_C */
|
||||
#if defined(MBEDTLS_SSL_CLI_C)
|
||||
if( endpoint == MBEDTLS_SSL_IS_CLIENT )
|
||||
{
|
||||
key_enc = traffic_keys->client_write_key;
|
||||
key_dec = traffic_keys->server_write_key;
|
||||
iv_enc = traffic_keys->client_write_iv;
|
||||
iv_dec = traffic_keys->server_write_iv;
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_SSL_CLI_C */
|
||||
{
|
||||
/* should not happen */
|
||||
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
||||
}
|
||||
|
||||
memcpy( transform->iv_enc, iv_enc, traffic_keys->iv_len );
|
||||
memcpy( transform->iv_dec, iv_dec, traffic_keys->iv_len );
|
||||
|
||||
if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_enc,
|
||||
key_enc, cipher_info->key_bitlen,
|
||||
MBEDTLS_ENCRYPT ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_dec,
|
||||
key_dec, cipher_info->key_bitlen,
|
||||
MBEDTLS_DECRYPT ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup other fields in SSL transform
|
||||
*/
|
||||
|
||||
if( ( ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ) != 0 )
|
||||
transform->taglen = 8;
|
||||
else
|
||||
transform->taglen = 16;
|
||||
|
||||
transform->ivlen = traffic_keys->iv_len;
|
||||
transform->maclen = 0;
|
||||
transform->fixed_ivlen = transform->ivlen;
|
||||
transform->minor_ver = MBEDTLS_SSL_MINOR_VERSION_4;
|
||||
|
||||
/* We add the true record content type (1 Byte) to the plaintext and
|
||||
* then pad to the configured granularity. The mimimum length of the
|
||||
* type-extended and padded plaintext is therefore the padding
|
||||
* granularity. */
|
||||
transform->minlen =
|
||||
transform->taglen + MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
|
||||
|
|
|
@ -498,4 +498,37 @@ int mbedtls_ssl_tls1_3_create_psk_binder( mbedtls_ssl_context *ssl,
|
|||
unsigned char const *transcript,
|
||||
unsigned char *result );
|
||||
|
||||
/**
|
||||
* \bref Setup an SSL transform structure representing the
|
||||
* record protection mechanism used by TLS 1.3
|
||||
*
|
||||
* \param transform The SSL transform structure to be created. This must have
|
||||
* been initialized through mbedtls_ssl_transform_init() and
|
||||
* not used in any other way prior to calling this function.
|
||||
* In particular, this function does not clean up the
|
||||
* transform structure prior to installing the new keys.
|
||||
* \param endpoint Indicates whether the transform is for the client
|
||||
* (value #MBEDTLS_SSL_IS_CLIENT) or the server
|
||||
* (value #MBEDTLS_SSL_IS_SERVER).
|
||||
* \param ciphersuite The numerical identifier for the ciphersuite to use.
|
||||
* This must be one of the identifiers listed in
|
||||
* ssl_ciphersuites.h.
|
||||
* \param traffic_keys The key material to use. No reference is stored in
|
||||
* the SSL transform being generated, and the caller
|
||||
* should destroy the key material afterwards.
|
||||
* \param ssl (Debug-only) The SSL context to use for debug output
|
||||
* in case of failure. This parameter is only needed if
|
||||
* #MBEDTLS_DEBUG_C is set, and is ignored otherwise.
|
||||
*
|
||||
* \return \c 0 on success. In this case, \p transform is ready to
|
||||
* be used with mbedtls_ssl_transform_decrypt() and
|
||||
* mbedtls_ssl_transform_encrypt().
|
||||
* \return A negative error code on failure.
|
||||
*/
|
||||
int mbedtls_ssl_tls13_populate_transform( mbedtls_ssl_transform *transform,
|
||||
int endpoint,
|
||||
int ciphersuite,
|
||||
mbedtls_ssl_key_set const *traffic_keys,
|
||||
mbedtls_ssl_context *ssl );
|
||||
|
||||
#endif /* MBEDTLS_SSL_TLS1_3_KEYS_H */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue