Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DTLS 1.3: Add dtls13_prepare_record_header #3

Open
wants to merge 4 commits into
base: dtls1.3-pr
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions include/openssl/dtls1.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ extern "C" {

# define DTLS1_HM_HEADER_LENGTH 12

/* DTLSv1.3: Statically fixed to 5 bytes (first byte, 16-bit Sequence ID
and 16-bit Length field).*/
# define DTLS13_UNIFIED_HEADER_LENGTH 5

# define DTLS1_HM_BAD_FRAGMENT -2
# define DTLS1_HM_FRAGMENT_RETRY -3

Expand All @@ -51,6 +55,13 @@ extern "C" {

# define DTLS1_TMO_ALERT_COUNT 12

/* DTLS 1.3 unified header */
#define DTLS13_CBIT 0x10
#define DTLS13_SBIT 0x08
#define DTLS13_LBIT 0x04
#define DTLS13_FIXED_BITS 0x20
#define DTLS13_EPOCH_MASK 0x03

#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion ssl/record/methods/build.info
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ ENDIF

SOURCE[../../../libssl]=\
tls_common.c ssl3_meth.c tls1_meth.c tls13_meth.c tlsany_meth.c \
dtls_meth.c tls_multib.c $KTLSSRC
dtls_meth.c dtls13_meth.c tls_multib.c $KTLSSRC

# For shared builds we need to include the sources needed in providers
# (ssl3_cbc.c) in libssl as well.
Expand Down
67 changes: 67 additions & 0 deletions ssl/record/methods/dtls13_meth.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright 2018-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/

#include "../../ssl_local.h"
#include "recmethod_local.h"

int dtls13_prepare_record_header(OSSL_RECORD_LAYER *rl,
WPACKET *thispkt,
OSSL_RECORD_TEMPLATE *templ,
uint8_t rectype,
unsigned char **recdata)
{
size_t maxcomplen;

*recdata = NULL;

maxcomplen = templ->buflen;
if (rl->compctx != NULL)
maxcomplen += SSL3_RT_MAX_COMPRESSED_OVERHEAD;

if (rectype == SSL3_RT_APPLICATION_DATA) {
/* DTLSCiphertext*/
unsigned char first_byte;

/*TODO (DTLSv1.3): Hardcoded first byte. Statically forced to use no Connection ID,
16-bit Sequence ID and 16-bit Length field. Implement variable length fields*/
first_byte = DTLS13_FIXED_BITS | DTLS13_SBIT | DTLS13_LBIT; // CBIT is not set
/* The two low bits (0x03) include the low-order two bits of the epoch.*/
first_byte |= (rl->epoch & DTLS13_EPOCH_MASK);

if (!WPACKET_put_bytes_u8(thispkt, first_byte)
|| !WPACKET_put_bytes_u8(thispkt, rl->sequence[SEQ_NUM_SIZE - 2])
|| !WPACKET_put_bytes_u8(thispkt, rl->sequence[SEQ_NUM_SIZE - 1])
|| !WPACKET_put_bytes_u16(thispkt, templ->buflen)
|| (rl->eivlen > 0
&& !WPACKET_allocate_bytes(thispkt, rl->eivlen, NULL))
|| (maxcomplen > 0
&& !WPACKET_reserve_bytes(thispkt, maxcomplen,
recdata))) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
} else {
/* DTLSPlainText record */
if (!WPACKET_put_bytes_u8(thispkt, rectype)
|| !WPACKET_put_bytes_u16(thispkt, templ->version)
|| !WPACKET_put_bytes_u16(thispkt, rl->epoch)
|| !WPACKET_memcpy(thispkt, &(rl->sequence[2]), 6)
|| !WPACKET_start_sub_packet_u16(thispkt)
|| (rl->eivlen > 0
&& !WPACKET_allocate_bytes(thispkt, rl->eivlen, NULL))
|| (maxcomplen > 0
&& !WPACKET_reserve_bytes(thispkt, maxcomplen,
recdata))) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}

return 1;
}
5 changes: 5 additions & 0 deletions ssl/record/methods/recmethod_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,11 @@ int dtls_prepare_record_header(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templ,
uint8_t rectype,
unsigned char **recdata);
int dtls13_prepare_record_header(OSSL_RECORD_LAYER *rl,
WPACKET *thispkt,
OSSL_RECORD_TEMPLATE *templ,
uint8_t rectype,
unsigned char **recdata);
int dtls_post_encryption_processing(OSSL_RECORD_LAYER *rl,
size_t mac_size,
OSSL_RECORD_TEMPLATE *thistempl,
Expand Down
51 changes: 40 additions & 11 deletions ssl/record/methods/tls13_meth.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ static int tls13_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *recs,
size_t macsize)
{
EVP_CIPHER_CTX *ctx;
/* Header length for both TLS1.3 and our DTLS1.3 implementation is 5 bytes,
matching SSL3_RT_HEADER_LENGTH. Future DTLS1.3 may need adjustments. */
unsigned char iv[EVP_MAX_IV_LENGTH], recheader[SSL3_RT_HEADER_LENGTH];
size_t ivlen, offset, loop, hdrlen;
unsigned char *staticiv;
Expand Down Expand Up @@ -135,16 +137,43 @@ static int tls13_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *recs,
}

/* Set up the AAD */
if (!WPACKET_init_static_len(&wpkt, recheader, sizeof(recheader), 0)
|| !WPACKET_put_bytes_u8(&wpkt, rec->type)
|| !WPACKET_put_bytes_u16(&wpkt, rec->rec_version)
|| !WPACKET_put_bytes_u16(&wpkt, rec->length + rl->taglen)
|| !WPACKET_get_total_written(&wpkt, &hdrlen)
|| hdrlen != SSL3_RT_HEADER_LENGTH
|| !WPACKET_finish(&wpkt)) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
WPACKET_cleanup(&wpkt);
return 0;
if (rl->isdtls) {
/* DTLSv1.3 Ciphertext record:
Statically forced to use no CID, 16-bit Sequence ID and 16-bit Length.*/
unsigned char first_byte = DTLS13_FIXED_BITS;
first_byte |= DTLS13_SBIT | DTLS13_LBIT;
first_byte |= (rl->epoch & DTLS13_EPOCH_MASK);

if (!WPACKET_init_static_len(&wpkt, recheader, sizeof(recheader), 0)
|| !WPACKET_put_bytes_u8(&wpkt, first_byte)
|| !WPACKET_put_bytes_u8(&wpkt, rl->sequence[SEQ_NUM_SIZE - 2])
|| !((first_byte & DTLS13_SBIT)
? WPACKET_put_bytes_u8(&wpkt,
rl->sequence[SEQ_NUM_SIZE - 1])
: 1)
|| !((first_byte & DTLS13_LBIT)
? WPACKET_put_bytes_u16(&wpkt, rec->length)
: 1)
|| !WPACKET_get_total_written(&wpkt, &hdrlen)
|| hdrlen != DTLS13_UNIFIED_HEADER_LENGTH
|| !WPACKET_finish(&wpkt)) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
WPACKET_cleanup(&wpkt);
return 0;
}
} else {
//TLSCiphertext record
if (!WPACKET_init_static_len(&wpkt, recheader, sizeof(recheader), 0)
|| !WPACKET_put_bytes_u8(&wpkt, rec->type)
|| !WPACKET_put_bytes_u16(&wpkt, rec->rec_version)
|| !WPACKET_put_bytes_u16(&wpkt, rec->length + rl->taglen)
|| !WPACKET_get_total_written(&wpkt, &hdrlen)
|| hdrlen != SSL3_RT_HEADER_LENGTH
|| !WPACKET_finish(&wpkt)) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
WPACKET_cleanup(&wpkt);
return 0;
}
}

/*
Expand Down Expand Up @@ -338,7 +367,7 @@ struct record_functions_st dtls_1_3_funcs = {
tls_allocate_write_buffers_default,
tls_initialise_write_packets_default,
tls13_get_record_type,
dtls_prepare_record_header,
dtls13_prepare_record_header,
tls13_add_record_padding,
tls_prepare_for_encryption_default,
dtls_post_encryption_processing,
Expand Down
19 changes: 14 additions & 5 deletions ssl/record/methods/tls_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,16 @@ int tls_setup_write_buffer(OSSL_RECORD_LAYER *rl, size_t numwpipes,
size_t contenttypelen = 0;

if (firstlen == 0 || (numwpipes > 1 && nextlen == 0)) {
if (rl->isdtls)
headerlen = DTLS1_RT_HEADER_LENGTH + 1;
else
if (rl->isdtls) {
if (rl->version == DTLS1_3_VERSION)
headerlen = DTLS13_UNIFIED_HEADER_LENGTH;
else
headerlen = DTLS1_RT_HEADER_LENGTH + 1;
} else
headerlen = SSL3_RT_HEADER_LENGTH;

/* TLSv1.3 adds an extra content type byte after payload data */
if (rl->version == TLS1_3_VERSION)
if (rl->version == TLS1_3_VERSION || rl->version == DTLS1_3_VERSION)
contenttypelen = 1;

#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0
Expand Down Expand Up @@ -1557,7 +1560,13 @@ int tls_initialise_write_packets_default(OSSL_RECORD_LAYER *rl,

#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0
align = (size_t)TLS_BUFFER_get_buf(wb);
align += rl->isdtls ? DTLS1_RT_HEADER_LENGTH : SSL3_RT_HEADER_LENGTH;
if (rl->isdtls) {
if (rl->version == DTLS1_3_VERSION)
align += DTLS13_UNIFIED_HEADER_LENGTH;
else
align += DTLS1_RT_HEADER_LENGTH;
} else
align += SSL3_RT_HEADER_LENGTH;
align = SSL3_ALIGN_PAYLOAD - 1
- ((align - 1) % SSL3_ALIGN_PAYLOAD);
#endif
Expand Down