Skip to content

Commit

Permalink
[nrf noup] Backport DTLS CID support compilant with RFC-9146
Browse files Browse the repository at this point in the history
-Backported hannestschofenig's
 Mbed-TLS/mbedtls#5061
 to mbed TLS 3.0. This makes DTLS CID support compliant with RFC-9146.

ref: NCSDK-15193

Signed-off-by: Pete Skeggs <peter.skeggs@nordicsemi.no>
Signed-off-by: Frank Audun Kvamtrø <frank.kvamtro@nordicsemi.no>
  • Loading branch information
plskeggs authored and Joakim Andersson committed Jun 9, 2022
1 parent 6824250 commit cf39070
Showing 1 changed file with 198 additions and 22 deletions.
220 changes: 198 additions & 22 deletions library/ssl_msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,28 +377,72 @@ static int ssl_parse_inner_plaintext( unsigned char const *content,
}
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID || MBEDTLS_SSL_PROTO_TLS1_3 */

/* `add_data` must have size 13 Bytes if the CID extension is disabled,
* and 13 + 1 + CID-length Bytes if the CID extension is enabled. */
/* The size of the `add_data` structure depends on various
* factors, namely
*
* 1) CID functionality disabled
*
* size = 13 bytes
*
* 2) CID functionality based on RFC 9146 enabled
*
* size = 8 + 1 + 1 + 1 + 2 + 2 + 6 + 2 + CID-length
* = 23 + CID-length
*
* 3) CID functionality based on legacy CID version
according to draft-ietf-tls-dtls-connection-id-05
* https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05
*
* size = 13 + 1 + CID-length
*
* More information about the CID usage:
*
* Per Section 5.3 of draft-ietf-tls-dtls-connection-id-05 the
* size of the additional data structure is calculated as:
*
* additional_data =
* 8: seq_num +
* 1: tls12_cid +
* 2: DTLSCipherText.version +
* n: cid +
* 1: cid_length +
* 2: length_of_DTLSInnerPlaintext
*
* Per RFC 9146 the size of the add_data structure is calculated as:
*
* additional_data =
* 8: seq_num_placeholder +
* 1: tls12_cid +
* 1: cid_length +
* 1: tls12_cid +
* 2: DTLSCiphertext.version +
* 2: epoch +
* 6: sequence_number +
* n: cid +
* 2: length_of_DTLSInnerPlaintext
*
*/
static void ssl_extract_add_data_from_record( unsigned char* add_data,
size_t *add_data_len,
mbedtls_record *rec,
unsigned minor_ver,
size_t taglen )
{
/* Quoting RFC 5246 (TLS 1.2):
/* Several types of ciphers have been defined for use with TLS and DTLS,
* and the MAC calculations for those ciphers differ slightly. Further
* variants were added when the CID functionality was added with RFC 9146.
* This implementations also considers the use of a legacy version of the
* CID specification published in draft-ietf-tls-dtls-connection-id-05,
* which is used in deployments.
*
* We will distinguish between the non-CID and the CID cases below.
*
* additional_data = seq_num + TLSCompressed.type +
* TLSCompressed.version + TLSCompressed.length;
* --- Non-CID cases ---
*
* For the CID extension, this is extended as follows
* (quoting draft-ietf-tls-dtls-connection-id-05,
* https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05):
* Quoting RFC 5246 (TLS 1.2):
*
* additional_data = seq_num + DTLSPlaintext.type +
* DTLSPlaintext.version +
* cid +
* cid_length +
* length_of_DTLSInnerPlaintext;
* additional_data = seq_num + TLSCompressed.type +
* TLSCompressed.version + TLSCompressed.length;
*
* For TLS 1.3, the record sequence number is dropped from the AAD
* and encoded within the nonce of the AEAD operation instead.
Expand All @@ -415,47 +459,156 @@ static void ssl_extract_add_data_from_record( unsigned char* add_data,
*
* TLSCiphertext.length = TLSInnerPlaintext.length + taglen.
*
*/
* --- CID cases ---
*
* RFC 9146 uses a common pattern when constructing the data
* passed into a MAC / AEAD cipher.
*
* Data concatenation for MACs used with block ciphers with
* Encrypt-then-MAC Processing (with CID):
*
* data = seq_num_placeholder +
* tls12_cid +
* cid_length +
* tls12_cid +
* DTLSCiphertext.version +
* epoch +
* sequence_number +
* cid +
* DTLSCiphertext.length +
* IV +
* ENC(content + padding + padding_length)
*
* Data concatenation for MACs used with block ciphers (with CID):
*
* data = seq_num_placeholder +
* tls12_cid +
* cid_length +
* tls12_cid +
* DTLSCiphertext.version +
* epoch +
* sequence_number +
* cid +
* length_of_DTLSInnerPlaintext +
* DTLSInnerPlaintext.content +
* DTLSInnerPlaintext.real_type +
* DTLSInnerPlaintext.zeros
*
* AEAD ciphers use the following additional data calculation (with CIDs):
*
* additional_data = seq_num_placeholder +
* tls12_cid +
* cid_length +
* tls12_cid +
* DTLSCiphertext.version +
* epoch +
* sequence_number +
* cid +
* length_of_DTLSInnerPlaintext
*
* Section 5.3 of draft-ietf-tls-dtls-connection-id-05 (for legacy CID use)
* defines the additional data calculation as follows:
*
* additional_data = seq_num +
* tls12_cid +
* DTLSCipherText.version +
* cid +
* cid_length +
* length_of_DTLSInnerPlaintext
*/

unsigned char *cur = add_data;
size_t ad_len_field = rec->data_len;

#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
size_t ad_len_field = rec->data_len;
const unsigned char seq_num_placeholder[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */

#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 )
{
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
/* 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;
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
}
else
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
{
((void) minor_ver);
((void) taglen);
memcpy( cur, rec->ctr, sizeof( rec->ctr ) );
cur += sizeof( rec->ctr );

#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
if( rec->cid_len != 0 )
{
// seq_num_placeholder
memcpy( cur, seq_num_placeholder, sizeof(seq_num_placeholder) );
cur += sizeof( seq_num_placeholder );

// tls12_cid type
*cur = rec->type;
cur++;

// cid_length
*cur = rec->cid_len;
cur++;
}
else
{
// epoch + sequence number
memcpy( cur, rec->ctr, sizeof( rec->ctr ) );
cur += sizeof( rec->ctr );
}
#else
// epoch + sequence number
memcpy(cur, rec->ctr, sizeof(rec->ctr));
cur += sizeof(rec->ctr);
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
}

// type
*cur = rec->type;
cur++;

// version
memcpy( cur, rec->ver, sizeof( rec->ver ) );
cur += sizeof( rec->ver );

#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
if( rec->cid_len != 0 )
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_LEGACY)
if (rec->cid_len != 0)
{
memcpy( cur, rec->cid, rec->cid_len );
// CID
memcpy(cur, rec->cid, rec->cid_len);
cur += rec->cid_len;

// cid_length
*cur = rec->cid_len;
cur++;

MBEDTLS_PUT_UINT16_BE( ad_len_field, cur, 0 );
cur += 2;
}
else
#elif defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
if( rec->cid_len != 0 )
{
// epoch + sequence number
memcpy(cur, rec->ctr, sizeof(rec->ctr));
cur += sizeof(rec->ctr);

// CID
memcpy( cur, rec->cid, rec->cid_len );
cur += rec->cid_len;

// length of inner plaintext
cur[0] = ( ad_len_field >> 8 ) & 0xFF;
cur[1] = ( ad_len_field >> 0 ) & 0xFF;
//MBEDTLS_PUT_UINT16_BE( ad_len_field, cur, 0 );
cur += 2;
}
else
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
{
MBEDTLS_PUT_UINT16_BE( ad_len_field, cur, 0 );
Expand Down Expand Up @@ -525,7 +678,13 @@ int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
mbedtls_cipher_mode_t mode;
int auth_done = 0;
unsigned char * data;
unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_OUT_LEN_MAX ];
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
unsigned char add_data[23 + MBEDTLS_SSL_CID_OUT_LEN_MAX];
#elif defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_LEGACY)
unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_OUT_LEN_MAX];
#else
unsigned char add_data[13];
#endif
size_t add_data_len;
size_t post_avail;

Expand Down Expand Up @@ -919,13 +1078,30 @@ int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
{
unsigned char mac[MBEDTLS_SSL_MAC_ADD];

/*
/* MAC computation (without CID):
*
* MAC(MAC_write_key, seq_num +
* TLSCipherText.type +
* TLSCipherText.version +
* length_of( (IV +) ENC(...) ) +
* IV +
* ENC(content + padding + padding_length));
*
* MAC calculation (with CID):
*
* MAC(MAC_write_key,
* seq_num_placeholder +
* tls12_cid +
* cid_length +
* tls12_cid +
* DTLSCiphertext.version +
* epoch +
* sequence_number +
* cid +
* DTLSCiphertext.length +
* IV +
* ENC(content + padding + padding_length)
* );
*/

if( post_avail < transform->maclen)
Expand Down

0 comments on commit cf39070

Please sign in to comment.