Support DTLS 1.3 Unified Headers

Also set correct AAD for DTLS 1.3 message de-/encryption.

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/25668)
This commit is contained in:
Frederik Wedel-Heinen 2024-10-21 11:05:25 +02:00 committed by Tomas Mraz
parent 374768c6cf
commit 42d467380c
11 changed files with 477 additions and 136 deletions

View file

@ -40,7 +40,7 @@ as a feature request in issue ###########.
### DTLSv1.3 connection id
OpenSSL does not support Connection ID's (RFC 9146). Notably Openssl DTLSv1.3 clients
OpenSSL does not support Connection IDs (RFC 9146). Notably Openssl DTLSv1.3 clients
will not offer the "connection_id" extension even though RFC 9147 states:
> DTLS clients which do not want to receive a Connection ID SHOULD still offer
@ -88,14 +88,12 @@ A summary of larger work items that needs to be addressed.
Notice that some of the requirements mentioned in [List of DTLSv1.3 requirements](#list-of-dtls-13-requirements)
is not covered by these workitems and must be implemented separately.
| Summary | #PR |
|-----------------------------------------------------|----------------|
| ACK messages | - |
| Use HelloRetryRequest instead of HelloVerifyRequest | #22985, #22400 |
| ClientHello | #23320 |
| EndOfEarlyData message | - |
| Variable length header | - |
| DTLSv1.3 Fuzzer | - |
| Summary | #PR |
|-----------------------------------------------------|--------|
| ACK messages | #25119 |
| Use HelloRetryRequest instead of HelloVerifyRequest | #22985 |
| EndOfEarlyData message | - |
| DTLSv1.3 Fuzzer | - |
### Changes from DTLS 1.2 and/or TLS 1.3

View file

@ -77,6 +77,10 @@ The connection uses the DTLSv1 protocol
The connection uses the DTLSv1.2 protocol
=item DTLSv1.3
The connection uses the DTLSv1.3 protocol
=item QUICv1
The connection uses the QUICv1 protocol.

View file

@ -22,7 +22,7 @@
extern "C" {
#endif
#include <openssl/opensslconf.h>
# include <openssl/opensslconf.h>
/* DTLS*_VERSION constants are defined in prov_ssl.h */
# ifndef OPENSSL_NO_DEPRECATED_3_0
@ -39,6 +39,7 @@ extern "C" {
# define DTLS1_COOKIE_LENGTH 255
# define DTLS1_RT_HEADER_SEQ_OFFS 5
# define DTLS1_RT_HEADER_SEQ_LEN 6
# define DTLS1_RT_HEADER_LENGTH 13
# define DTLS1_HM_HEADER_LENGTH 12
@ -52,7 +53,19 @@ extern "C" {
# define DTLS1_TMO_ALERT_COUNT 12
#ifdef __cplusplus
/* DTLS 1.3 Unified header */
# define DTLS13_UNI_HDR_FIXED_LENGTH 5
# define DTLS13_UNI_HDR_FIX_BITS 0x20
# define DTLS13_UNI_HDR_CID_BIT 0x10
# define DTLS13_UNI_HDR_SEQ_BIT 0x08
# define DTLS13_UNI_HDR_SEQ_OFF 1
# define DTLS13_UNI_HDR_LEN_BIT 0x04
# define DTLS13_UNI_HDR_FIX_BITS_MASK 0xe0
# define DTLS13_UNI_HDR_EPOCH_BITS_MASK 0x03
# define DTLS13_CIPHERTEXT_MINSIZE 16
# ifdef __cplusplus
}
#endif
# endif
#endif

View file

@ -923,7 +923,7 @@ size_t dtls1_min_mtu(SSL_CONNECTION *s)
size_t DTLS_get_data_mtu(const SSL *ssl)
{
size_t mac_overhead, int_overhead, blocksize, ext_overhead;
size_t mac_overhead, int_overhead, blocksize, ext_overhead, rechdrlen = 0;
const SSL_CIPHER *ciph = SSL_get_current_cipher(ssl);
size_t mtu;
const SSL_CONNECTION *s = SSL_CONNECTION_FROM_CONST_SSL_ONLY(ssl);
@ -945,10 +945,33 @@ size_t DTLS_get_data_mtu(const SSL *ssl)
else
int_overhead += mac_overhead;
if (SSL_version(ssl) == DTLS1_3_VERSION) {
switch (SSL_get_state(ssl)) {
case TLS_ST_BEFORE:
case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
case TLS_ST_CR_SRVR_HELLO:
case TLS_ST_CW_CLNT_HELLO:
case TLS_ST_CW_COMP_CERT:
case TLS_ST_CW_KEY_EXCH:
case TLS_ST_SW_HELLO_REQ:
case TLS_ST_SR_CLNT_HELLO:
case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
case TLS_ST_SW_SRVR_HELLO:
case TLS_ST_CR_HELLO_REQ:
rechdrlen = DTLS1_RT_HEADER_LENGTH;
break;
default:
rechdrlen = DTLS13_UNI_HDR_FIXED_LENGTH;
break;
}
} else {
rechdrlen = DTLS1_RT_HEADER_LENGTH;
}
/* Subtract external overhead (e.g. IV/nonce, separate MAC) */
if (ext_overhead + DTLS1_RT_HEADER_LENGTH >= mtu)
if (ext_overhead + rechdrlen >= mtu)
return 0;
mtu -= ext_overhead + DTLS1_RT_HEADER_LENGTH;
mtu -= ext_overhead + rechdrlen;
/* Round encrypted payload down to cipher block size (for CBC etc.)
* No check for overflow since 'mtu % blocksize' cannot exceed mtu. */

View file

@ -105,6 +105,24 @@ static void dtls_set_in_init(OSSL_RECORD_LAYER *rl, int in_init)
rl->in_init = in_init;
}
size_t dtls_get_rec_header_size(uint8_t hdr_first_byte)
{
size_t size = 0;
if (DTLS13_UNI_HDR_FIX_BITS_IS_SET(hdr_first_byte)
&& ossl_assert(!DTLS13_UNI_HDR_CID_BIT_IS_SET(hdr_first_byte))) {
/* DTLSv1.3 unified record header */
size = 1;
size += DTLS13_UNI_HDR_SEQ_BIT_IS_SET(hdr_first_byte) ? 2 : 1;
size += DTLS13_UNI_HDR_LEN_BIT_IS_SET(hdr_first_byte) ? 2 : 0;
} else {
/* DTLSv1.0, DTLSv1.2 or unencrypted DTLSv1.3 record header */
size = DTLS1_RT_HEADER_LENGTH;
}
return size;
}
static int dtls_process_record(OSSL_RECORD_LAYER *rl, DTLS_BITMAP *bitmap)
{
int i;
@ -112,6 +130,7 @@ static int dtls_process_record(OSSL_RECORD_LAYER *rl, DTLS_BITMAP *bitmap)
TLS_RL_RECORD *rr;
int imac_size;
size_t mac_size = 0;
size_t rechdrsize = dtls_get_rec_header_size(rl->packet[0]);
unsigned char md[EVP_MAX_MD_SIZE];
SSL_MAC_BUF macbuf = { NULL, 0 };
int ret = 0;
@ -119,10 +138,10 @@ static int dtls_process_record(OSSL_RECORD_LAYER *rl, DTLS_BITMAP *bitmap)
rr = &rl->rrec[0];
/*
* At this point, rl->packet_length == DTLS1_RT_HEADER_LENGTH + rr->length,
* At this point, rl->packet_length == rechdrsize + rr->length,
* and we have that many bytes in rl->packet
*/
rr->input = &(rl->packet[DTLS1_RT_HEADER_LENGTH]);
rr->input = rl->packet + rechdrsize;
/*
* ok, we can now read from 'rl->packet' data into 'rr'. rr->input
@ -342,7 +361,8 @@ static int dtls_copy_rlayer_record(OSSL_RECORD_LAYER *rl, pitem *item)
memcpy(&rl->rrec[0], &(rdata->rrec), sizeof(TLS_RL_RECORD));
/* Set proper sequence number for mac calculation */
memcpy(&(rl->sequence[2]), &(rdata->packet[5]), 6);
assert(sizeof(rl->sequence) == sizeof(rdata->rrec.seq_num));
memcpy(rl->sequence, rdata->rrec.seq_num, sizeof(rl->sequence));
return 1;
}
@ -366,14 +386,13 @@ static int dtls_retrieve_rlayer_buffered_record(OSSL_RECORD_LAYER *rl,
}
/* rfc9147 section 4.2.3 */
int dtls_crypt_sequence_number(EVP_CIPHER_CTX *ctx, unsigned char *seq,
int dtls_crypt_sequence_number(EVP_CIPHER_CTX *ctx, unsigned char *seq, size_t seqlen,
unsigned char *rec_data, size_t rec_data_offs)
{
unsigned char mask[16];
int outlen, inlen;
unsigned char *iv, *in;
size_t i;
size_t seq_len = 6;
if (ossl_assert(sizeof(mask) > rec_data_offs))
inlen = (int)(sizeof(mask) - rec_data_offs);
@ -393,7 +412,10 @@ int dtls_crypt_sequence_number(EVP_CIPHER_CTX *ctx, unsigned char *seq,
|| outlen != 0)
return 0;
for (i = 0; i < seq_len; i++)
if (!ossl_assert(seqlen <= sizeof(mask)))
return 0;
for (i = 0; i < seqlen; i++)
seq[i] ^= mask[i];
OPENSSL_cleanse(mask, sizeof(mask));
@ -412,13 +434,17 @@ int dtls_crypt_sequence_number(EVP_CIPHER_CTX *ctx, unsigned char *seq,
*/
int dtls_get_more_records(OSSL_RECORD_LAYER *rl)
{
int ssl_major, ssl_minor;
int rret;
size_t more, n;
size_t more, nread = 0;
TLS_RL_RECORD *rr;
unsigned char *p = NULL;
DTLS_BITMAP *bitmap;
unsigned int is_next_epoch;
unsigned char recseqnum[6];
size_t recseqnumlen = 0;
size_t rechdrlen = 0;
size_t recseqnumoffs = 0;
memset(recseqnum, 0, sizeof(recseqnum));
rl->num_recs = 0;
rl->curr_rec = 0;
@ -443,10 +469,13 @@ int dtls_get_more_records(OSSL_RECORD_LAYER *rl)
/* get something from the wire */
/* check if we have the header */
if ((rl->rstate != SSL_ST_READ_BODY) ||
(rl->packet_length < DTLS1_RT_HEADER_LENGTH)) {
if (rl->rstate != SSL_ST_READ_BODY
|| rl->packet_length < DTLS1_RT_HEADER_LENGTH) {
PACKET dtlsrecord;
unsigned int record_type, record_version, epoch, length;
rret = rl->funcs->read_n(rl, DTLS1_RT_HEADER_LENGTH,
TLS_BUFFER_get_len(&rl->rbuf), 0, 1, &n);
TLS_BUFFER_get_len(&rl->rbuf), 0, 1, &nread);
/* read timeout is handled by dtls1_read_bytes */
if (rret < OSSL_RECORD_RETURN_SUCCESS) {
/* RLAYERfatal() already called if appropriate */
@ -461,25 +490,112 @@ int dtls_get_more_records(OSSL_RECORD_LAYER *rl)
rl->rstate = SSL_ST_READ_BODY;
p = rl->packet;
if (!PACKET_buf_init(&dtlsrecord, rl->packet, rl->packet_length)
|| !PACKET_get_1(&dtlsrecord, &record_type)) {
rl->packet_length = 0;
goto again;
}
/* Pull apart the header into the DTLS1_RECORD */
rr->type = *(p++);
ssl_major = *(p++);
ssl_minor = *(p++);
rr->rec_version = (ssl_major << 8) | ssl_minor;
rr->type = (int)record_type;
/* sequence number is 64 bits, with top 2 bytes = epoch */
n2s(p, rr->epoch);
/*-
* rfc9147:
* Implementations can demultiplex DTLS 1.3 records by examining the first
* byte as follows:
* * If the first byte is alert(21), handshake(22), or ack(proposed, 26),
* the record MUST be interpreted as a DTLSPlaintext record.
* * If the first byte is any other value, then receivers MUST check to
* see if the leading bits of the first byte are 001. If so, the implementation
* MUST process the record as DTLSCiphertext; the true content type
* will be inside the protected portion.
* * Otherwise, the record MUST be rejected as if it had failed deprotection,
* as described in Section 4.5.2.
*/
if (rl->version == DTLS1_3_VERSION
&& rr->type != SSL3_RT_ALERT
&& rr->type != SSL3_RT_HANDSHAKE
/* TODO(DTLSv1.3): && rr->type != SSL3_RT_ACK depends on acknowledge implementation */
&& !DTLS13_UNI_HDR_FIX_BITS_IS_SET(rr->type)) {
/* Silently discard */
rr->length = 0;
rl->packet_length = 0;
goto again;
}
memcpy(&(rl->sequence[2]), p, 6);
p += 6;
if (DTLS13_UNI_HDR_FIX_BITS_IS_SET(rr->type)) {
/*
* rfc9147:
* receivers MUST check to if the leading bits of the first byte are 001.
* If so, the implementation MUST process the record as DTLSCiphertext;
*/
int cbitisset = DTLS13_UNI_HDR_CID_BIT_IS_SET(rr->type);
int sbitisset = DTLS13_UNI_HDR_SEQ_BIT_IS_SET(rr->type);
int lbitisset = DTLS13_UNI_HDR_LEN_BIT_IS_SET(rr->type);
uint16_t eebits = rr->type & DTLS13_UNI_HDR_EPOCH_BITS_MASK;
n2s(p, rr->length);
record_version = DTLS1_2_VERSION;
epoch = rl->epoch;
recseqnumlen = sbitisset ? 2 : 1;
recseqnumoffs = sizeof(recseqnum) - recseqnumlen;
if (/* OpenSSL does not support connection IDs: silently discard */
cbitisset
/*
* Naive approach? We expect sequence number to be filled already
* and then override the last bytes of the sequence number.
*/
|| !PACKET_copy_bytes(&dtlsrecord, recseqnum + recseqnumoffs, recseqnumlen)) {
rr->length = 0;
rl->packet_length = 0;
goto again;
}
/*
* rfc9147:
* The length field MAY be omitted by clearing the L bit, which means
* that the record consumes the entire rest of the datagram in the
* lower level transport
*/
length = TLS_BUFFER_get_len(&rl->rbuf) - dtls_get_rec_header_size(rr->type);
if ((lbitisset && !PACKET_get_net_2(&dtlsrecord, &length))
|| length == 0) {
rr->length = 0;
rl->packet_length = 0;
goto again;
}
/*
* We should not be getting records from a previous epoch so
* choose the current epoch if the bits match or else choose the
* next epoch with matching bits
*/
while (eebits != (epoch & DTLS13_UNI_HDR_EPOCH_BITS_MASK))
epoch++;
} else {
if (!PACKET_get_net_2(&dtlsrecord, &record_version)
|| !PACKET_get_net_2(&dtlsrecord, &epoch)
|| !PACKET_copy_bytes(&dtlsrecord, recseqnum, 6)
|| !PACKET_get_net_2(&dtlsrecord, &length)) {
rr->length = 0;
rl->packet_length = 0;
goto again;
}
recseqnumoffs = 0;
recseqnumlen = 6;
}
rechdrlen = PACKET_data(&dtlsrecord) - rl->packet;
rr->rec_version = (int)record_version;
rr->epoch = epoch;
rr->length = length;
if (rl->msg_callback != NULL)
rl->msg_callback(0, rr->rec_version, SSL3_RT_HEADER, rl->packet, DTLS1_RT_HEADER_LENGTH,
rl->cbarg);
rl->msg_callback(0, rr->rec_version, SSL3_RT_HEADER, rl->packet,
rechdrlen, rl->cbarg);
/*
* Lets check the version. We tolerate alerts that don't have the exact
@ -497,9 +613,9 @@ int dtls_get_more_records(OSSL_RECORD_LAYER *rl)
}
}
if (ssl_major !=
(rl->version == DTLS_ANY_VERSION ? DTLS1_VERSION_MAJOR
: rl->version >> 8)) {
if (rr->rec_version >> 8 !=
(rl->version == DTLS_ANY_VERSION ? DTLS1_VERSION_MAJOR
: rl->version >> 8)) {
/* wrong version, silently discard record */
rr->length = 0;
rl->packet_length = 0;
@ -531,10 +647,10 @@ int dtls_get_more_records(OSSL_RECORD_LAYER *rl)
if (rr->length > rl->packet_length - DTLS1_RT_HEADER_LENGTH) {
/* now rl->packet_length == DTLS1_RT_HEADER_LENGTH */
more = rr->length;
rret = rl->funcs->read_n(rl, more, more, 1, 1, &n);
more = rr->length - (nread - rechdrlen);
rret = rl->funcs->read_n(rl, more, more, 1, 1, &nread);
/* this packet contained a partial record, dump it */
if (rret < OSSL_RECORD_RETURN_SUCCESS || n != more) {
if (rret < OSSL_RECORD_RETURN_SUCCESS || nread != more) {
if (rl->alert != SSL_AD_NO_ALERT) {
/* read_n() called RLAYERfatal() */
return OSSL_RECORD_RETURN_FATAL;
@ -554,15 +670,18 @@ int dtls_get_more_records(OSSL_RECORD_LAYER *rl)
/*
* rfc9147:
* This procedure requires the ciphertext length to be at least 16 bytes.
* This procedure requires the ciphertext length to be at least
* DTLS13_CIPHERTEXT_MINSIZE (16) bytes.
* Receivers MUST reject shorter records as if they had failed deprotection
* TODO(DTLSv1.3): This check will need to be modified when support for variable
* length headers is added.
*/
if (rl->sn_enc_ctx != NULL
&& (rl->packet_length < DTLS1_RT_HEADER_LENGTH + 16
|| !dtls_crypt_sequence_number(rl->sn_enc_ctx, &(rl->sequence[2]),
rl->packet + DTLS1_RT_HEADER_LENGTH,
if (DTLS13_UNI_HDR_FIX_BITS_IS_SET(rr->type)
&& rl->version == DTLS1_3_VERSION
&& (!ossl_assert(rl->sn_enc_ctx != NULL)
|| !ossl_assert(rl->packet_length >= rechdrlen + DTLS13_CIPHERTEXT_MINSIZE)
|| !dtls_crypt_sequence_number(rl->sn_enc_ctx,
recseqnum + recseqnumoffs,
recseqnumlen,
rl->packet + rechdrlen,
rl->sn_enc_offs))) {
/* sequence number encryption failed dump record */
rr->length = 0;
@ -570,6 +689,9 @@ int dtls_get_more_records(OSSL_RECORD_LAYER *rl)
goto again;
}
memset(rl->sequence, 0, sizeof(rl->sequence));
memcpy(rl->sequence + 2, recseqnum, sizeof(recseqnum));
/* match epochs. NULL means the packet is dropped on the floor */
bitmap = dtls_get_bitmap(rl, rr, &is_next_epoch);
if (bitmap == NULL) {
@ -742,6 +864,7 @@ int dtls_prepare_record_header(OSSL_RECORD_LAYER *rl,
unsigned char **recdata)
{
size_t maxcomplen;
int unifiedheader = rl->version == DTLS1_3_VERSION && rl->epoch > 0;
*recdata = NULL;
@ -749,7 +872,26 @@ int dtls_prepare_record_header(OSSL_RECORD_LAYER *rl,
if (rl->compctx != NULL)
maxcomplen += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
if (!WPACKET_put_bytes_u8(thispkt, rectype)
if (unifiedheader) {
uint8_t fixedbits = 0x20;
uint8_t cbit = 0;
uint8_t sbit = DTLS13_UNI_HDR_SEQ_BIT;
uint8_t lbit = DTLS13_UNI_HDR_LEN_BIT;
uint8_t ebits = rl->epoch & DTLS13_UNI_HDR_EPOCH_BITS_MASK;
uint8_t unifiedhdrbits = fixedbits | cbit | sbit | lbit | ebits;
if (!WPACKET_put_bytes_u8(thispkt, unifiedhdrbits)
|| !WPACKET_memcpy(thispkt, rl->sequence + 6, 2)
|| !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;
}
} else {
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)
@ -757,10 +899,10 @@ int dtls_prepare_record_header(OSSL_RECORD_LAYER *rl,
|| (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;
&& !WPACKET_reserve_bytes(thispkt, maxcomplen, recdata))) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
return 1;
@ -784,6 +926,7 @@ int dtls_post_encryption_processing(OSSL_RECORD_LAYER *rl,
static size_t dtls_get_max_record_overhead(OSSL_RECORD_LAYER *rl)
{
size_t blocksize = 0, contenttypelen = 0;
size_t rchdrlen = tls_get_record_header_len(rl);
if (rl->enc_ctx != NULL &&
(EVP_CIPHER_CTX_get_mode(rl->enc_ctx) == EVP_CIPH_CBC_MODE))
@ -815,8 +958,7 @@ static size_t dtls_get_max_record_overhead(OSSL_RECORD_LAYER *rl)
* MTU size - so isn't very helpful. We just ignore potential expansion
* due to compression.
*/
return DTLS1_RT_HEADER_LENGTH + rl->eivlen + blocksize + rl->taglen
+ contenttypelen;
return rchdrlen + rl->eivlen + blocksize + rl->taglen + contenttypelen;
}
const OSSL_RECORD_METHOD ossl_dtls_record_method = {

View file

@ -423,7 +423,24 @@ int tls_default_read_n(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend,
int clearold, size_t *readbytes);
int tls_get_more_records(OSSL_RECORD_LAYER *rl);
int dtls_crypt_sequence_number(EVP_CIPHER_CTX *ctx, unsigned char *seq,
/* Returns true if the unified header fixed bits are set (rfc9147 section 4) */
#define DTLS13_UNI_HDR_FIX_BITS_IS_SET(byte) \
(((byte) & DTLS13_UNI_HDR_FIX_BITS_MASK) == DTLS13_UNI_HDR_FIX_BITS)
/* Returns true if the unified header connection id bit is set (rfc9147 section 4) */
#define DTLS13_UNI_HDR_CID_BIT_IS_SET(byte) \
(((byte) & DTLS13_UNI_HDR_CID_BIT) == DTLS13_UNI_HDR_CID_BIT)
/* Returns true if the unified header sequence number bit is set (rfc9147 section 4) */
#define DTLS13_UNI_HDR_SEQ_BIT_IS_SET(byte) \
(((byte) & DTLS13_UNI_HDR_SEQ_BIT) == DTLS13_UNI_HDR_SEQ_BIT)
/* Returns true if the unified header length bit is set (rfc9147 section 4) */
#define DTLS13_UNI_HDR_LEN_BIT_IS_SET(byte) \
(((byte) & DTLS13_UNI_HDR_LEN_BIT) == DTLS13_UNI_HDR_LEN_BIT)
size_t dtls_get_rec_header_size(uint8_t hdr_first_byte);
int dtls_crypt_sequence_number(EVP_CIPHER_CTX *ctx, unsigned char *seq, size_t seqlen,
unsigned char *rec_data, size_t rec_data_offs);
int dtls_get_more_records(OSSL_RECORD_LAYER *rl);
@ -440,6 +457,7 @@ int dtls_post_encryption_processing(OSSL_RECORD_LAYER *rl,
int tls_default_set_protocol_version(OSSL_RECORD_LAYER *rl, int version);
int tls_default_validate_record_header(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *re);
size_t tls_get_record_header_len(OSSL_RECORD_LAYER *rl);
int tls_do_compress(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *wr);
int tls_do_uncompress(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *rec);
int tls_default_post_process_record(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *rec);
@ -469,7 +487,6 @@ int tls_read_record(OSSL_RECORD_LAYER *rl, void **rechandle, int *rversion,
uint8_t *type, const unsigned char **data, size_t *datalen,
uint16_t *epoch, unsigned char *seq_num);
int tls_release_record(OSSL_RECORD_LAYER *rl, void *rechandle, size_t length);
int tls_default_set_protocol_version(OSSL_RECORD_LAYER *rl, int version);
int tls_set_protocol_version(OSSL_RECORD_LAYER *rl, int version);
void tls_set_plain_alerts(OSSL_RECORD_LAYER *rl, int allow);
void tls_set_first_handshake(OSSL_RECORD_LAYER *rl, int first);
@ -493,6 +510,8 @@ size_t tls_get_max_records_default(OSSL_RECORD_LAYER *rl, uint8_t type,
size_t tls_get_max_records_multiblock(OSSL_RECORD_LAYER *rl, uint8_t type,
size_t len, size_t maxfrag,
size_t *preffrag);
size_t tls_get_record_body_alignment_offset(OSSL_RECORD_LAYER *rl,
const unsigned char *rec);
int tls_allocate_write_buffers_default(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl, size_t *prefix);

View file

@ -112,7 +112,8 @@ static int tls13_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *recs,
EVP_CIPHER_CTX *enc_ctx;
unsigned char recheader[SSL3_RT_HEADER_LENGTH];
unsigned char tag[EVP_MAX_MD_SIZE];
size_t nonce_len, offset, loop, hdrlen, taglen;
size_t nonce_len, offset, loop, hdrlen, taglen, exphdrlen;
int isdtls, sbit = 0, addlen;
unsigned char *staticiv;
unsigned char *nonce;
unsigned char *seq = rl->sequence;
@ -132,6 +133,7 @@ static int tls13_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *recs,
enc_ctx = rl->enc_ctx; /* enc_ctx is ignored when rl->mac_ctx != NULL */
staticiv = rl->iv;
nonce = rl->nonce;
isdtls = rl->isdtls;
if (enc_ctx == NULL && rl->mac_ctx == NULL) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
@ -185,18 +187,46 @@ static int tls13_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *recs,
for (loop = 0; loop < SEQ_NUM_SIZE; loop++)
nonce[offset + loop] = staticiv[offset + loop] ^ seq[loop];
if (!tls_increment_sequence_ctr(rl)) {
if (!isdtls && !tls_increment_sequence_ctr(rl)) {
/* RLAYERfatal already called */
return 0;
}
/* Set up the AAD */
if (!WPACKET_init_static_len(&wpkt, recheader, sizeof(recheader), 0)
/*-
* Set up the additional data as described in rfc8446 section 5.2:
* "and the additional data input is the record header.
* I.e.,
* additional_data = TLSCiphertext.opaque_type ||
* TLSCiphertext.legacy_record_version ||
* TLSCiphertext.length"
* and in rfc1947 section 4:
* "The entire header value shown in Figure 4 (but prior to record number
* encryption; see Section 4.2.3) is used as the additional data value for
* the AEAD function. For instance, if the minimal variant is used, the
* Associated Data (AD) is 2 octets long."
*
* For DTLS: at this point rec->type is just the first byte of the variable
* header. So it is not an actual record type. The record type is set in
* tls13_post_process_record() for incoming records.
*/
if (isdtls) {
exphdrlen = dtls_get_rec_header_size(rec->type);
sbit = DTLS13_UNI_HDR_SEQ_BIT_IS_SET(rec->type);
addlen = DTLS13_UNI_HDR_LEN_BIT_IS_SET(rec->type);
} else {
exphdrlen = SSL3_RT_HEADER_LENGTH;
addlen = 1;
}
if ((isdtls && !ossl_assert(!DTLS13_UNI_HDR_CID_BIT_IS_SET(rec->type)))
|| !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)
|| (isdtls && (sbit ? !WPACKET_memcpy(&wpkt, rl->sequence + 6, 2)
: !WPACKET_memcpy(&wpkt, rl->sequence + 7, 1)))
|| (!isdtls && !WPACKET_put_bytes_u16(&wpkt, rec->rec_version))
|| (addlen && !WPACKET_put_bytes_u16(&wpkt, rec->length + rl->taglen))
|| !WPACKET_get_total_written(&wpkt, &hdrlen)
|| hdrlen != SSL3_RT_HEADER_LENGTH
|| hdrlen != exphdrlen
|| !WPACKET_finish(&wpkt)) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
WPACKET_cleanup(&wpkt);
@ -208,7 +238,7 @@ static int tls13_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *recs,
if ((mac_ctx = EVP_MAC_CTX_dup(rl->mac_ctx)) == NULL
|| !EVP_MAC_update(mac_ctx, nonce, nonce_len)
|| !EVP_MAC_update(mac_ctx, recheader, sizeof(recheader))
|| !EVP_MAC_update(mac_ctx, recheader, hdrlen)
|| !EVP_MAC_update(mac_ctx, rec->input, rec->length)
|| !EVP_MAC_final(mac_ctx, tag, &taglen, rl->taglen)) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
@ -248,12 +278,9 @@ static int tls13_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *recs,
* any AAD.
*/
if ((mode == EVP_CIPH_CCM_MODE
&& EVP_CipherUpdate(enc_ctx, NULL, &lenu, NULL,
(unsigned int)rec->length) <= 0)
|| EVP_CipherUpdate(enc_ctx, NULL, &lenu, recheader,
sizeof(recheader)) <= 0
|| EVP_CipherUpdate(enc_ctx, rec->data, &lenu, rec->input,
(unsigned int)rec->length) <= 0
&& EVP_CipherUpdate(enc_ctx, NULL, &lenu, NULL, (int)rec->length) <= 0)
|| EVP_CipherUpdate(enc_ctx, NULL, &lenu, recheader, (int)hdrlen) <= 0
|| EVP_CipherUpdate(enc_ctx, rec->data, &lenu, rec->input, (int)rec->length) <= 0
|| EVP_CipherFinal_ex(enc_ctx, rec->data + lenu, &lenf) <= 0
|| (size_t)(lenu + lenf) != rec->length) {
return 0;
@ -302,7 +329,8 @@ static int tls13_post_process_record(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *rec)
size_t end;
if (rec->length == 0
|| rec->type != SSL3_RT_APPLICATION_DATA) {
|| rl->isdtls ? !DTLS13_UNI_HDR_FIX_BITS_IS_SET(rec->type)
: rec->type != SSL3_RT_APPLICATION_DATA) {
RLAYERfatal(rl, SSL_AD_UNEXPECTED_MESSAGE,
SSL_R_BAD_RECORD_TYPE);
return 0;
@ -340,6 +368,15 @@ static uint8_t tls13_get_record_type(OSSL_RECORD_LAYER *rl,
* when encrypting in TLSv1.3. The "inner" record type encodes the "real"
* record type from the template.
*/
if (rl->isdtls) {
const unsigned char fixed = DTLS13_UNI_HDR_FIX_BITS;
const unsigned char sbit = DTLS13_UNI_HDR_SEQ_BIT;
const unsigned char lbit = DTLS13_UNI_HDR_LEN_BIT;
const unsigned char epochbits = DTLS13_UNI_HDR_EPOCH_BITS_MASK & rl->epoch;
return fixed | sbit | lbit | epochbits;
}
return SSL3_RT_APPLICATION_DATA;
}

View file

@ -626,12 +626,7 @@ int tls1_initialise_write_packets(OSSL_RECORD_LAYER *rl,
prefixtempl->type = SSL3_RT_APPLICATION_DATA;
wb = &bufs[0];
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0
align = (size_t)TLS_BUFFER_get_buf(wb) + SSL3_RT_HEADER_LENGTH;
align = SSL3_ALIGN_PAYLOAD - 1
- ((align - 1) % SSL3_ALIGN_PAYLOAD);
#endif
align = tls_get_record_body_alignment_offset(rl, TLS_BUFFER_get_buf(wb));
TLS_BUFFER_set_offset(wb, align);
if (!WPACKET_init_static_len(&pkt[0], TLS_BUFFER_get_buf(wb),

View file

@ -151,10 +151,7 @@ int tls_setup_write_buffer(OSSL_RECORD_LAYER *rl, size_t numwpipes,
const int version1_3 = rl->isdtls ? DTLS1_3_VERSION : TLS1_3_VERSION;
if (firstlen == 0 || (numwpipes > 1 && nextlen == 0)) {
if (rl->isdtls)
headerlen = DTLS1_RT_HEADER_LENGTH + 1;
else
headerlen = SSL3_RT_HEADER_LENGTH;
headerlen = tls_get_record_header_len(rl);
/* (D)TLSv1.3 adds an extra content type byte after payload data */
if (rl->version == version1_3)
@ -235,10 +232,7 @@ int tls_setup_read_buffer(OSSL_RECORD_LAYER *rl)
b = &rl->rbuf;
if (rl->isdtls)
headerlen = DTLS1_RT_HEADER_LENGTH;
else
headerlen = SSL3_RT_HEADER_LENGTH;
headerlen = tls_get_record_header_len(rl);
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0
maxalign = SSL3_ALIGN_PAYLOAD - 1;
@ -636,7 +630,7 @@ int tls_get_more_records(OSSL_RECORD_LAYER *rl)
|| !PACKET_get_net_2(&pkt, &version)
|| !PACKET_get_net_2_len(&pkt, &thisrr->length)) {
if (rl->msg_callback != NULL)
rl->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, rl->cbarg);
rl->msg_callback(0, 0, SSL3_RT_HEADER, p, SSL3_RT_HEADER_LENGTH, rl->cbarg);
RLAYERfatal(rl, SSL_AD_DECODE_ERROR, ERR_R_INTERNAL_ERROR);
return OSSL_RECORD_RETURN_FATAL;
}
@ -656,7 +650,8 @@ int tls_get_more_records(OSSL_RECORD_LAYER *rl)
}
if (rl->msg_callback != NULL)
rl->msg_callback(0, version, SSL3_RT_HEADER, p, 5, rl->cbarg);
rl->msg_callback(0, version, SSL3_RT_HEADER, p,
SSL3_RT_HEADER_LENGTH, rl->cbarg);
if (thisrr->length >
TLS_BUFFER_get_len(rbuf) - SSL3_RT_HEADER_LENGTH) {
@ -1562,6 +1557,21 @@ int tls_allocate_write_buffers_default(OSSL_RECORD_LAYER *rl,
return 1;
}
size_t tls_get_record_body_alignment_offset(OSSL_RECORD_LAYER *rl,
const unsigned char *rec)
{
size_t alignoffset = 0;
size_t headersize = tls_get_record_header_len(rl);
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0
alignoffset = (size_t)rec;
alignoffset += headersize;
alignoffset = SSL3_ALIGN_PAYLOAD - 1 - ((alignoffset - 1) % SSL3_ALIGN_PAYLOAD);
#endif
return alignoffset;
}
int tls_initialise_write_packets_default(OSSL_RECORD_LAYER *rl,
OSSL_RECORD_TEMPLATE *templates,
size_t numtempl,
@ -1579,13 +1589,7 @@ int tls_initialise_write_packets_default(OSSL_RECORD_LAYER *rl,
wb = &bufs[j];
wb->type = templates[j].type;
#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;
align = SSL3_ALIGN_PAYLOAD - 1
- ((align - 1) % SSL3_ALIGN_PAYLOAD);
#endif
align = tls_get_record_body_alignment_offset(rl, TLS_BUFFER_get_buf(wb));
TLS_BUFFER_set_offset(wb, align);
if (!WPACKET_init_static_len(thispkt, TLS_BUFFER_get_buf(wb),
@ -1689,8 +1693,9 @@ int tls_post_encryption_processing_default(OSSL_RECORD_LAYER *rl,
TLS_RL_RECORD *thiswr)
{
size_t origlen, len;
size_t headerlen = rl->isdtls ? DTLS1_RT_HEADER_LENGTH
: SSL3_RT_HEADER_LENGTH;
unsigned char *recordstart;
size_t rechdrlen;
size_t written;
/* Allocate bytes for the encryption overhead */
if (!WPACKET_get_length(thispkt, &origlen)
@ -1719,31 +1724,37 @@ int tls_post_encryption_processing_default(OSSL_RECORD_LAYER *rl,
}
if (!WPACKET_get_length(thispkt, &len)
|| !WPACKET_close(thispkt)) {
|| !WPACKET_close(thispkt)
|| !WPACKET_get_total_written(thispkt, &written)) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (rl->sn_enc_ctx != NULL) {
unsigned char *recordstart;
recordstart = WPACKET_get_curr(thispkt) - written;
recordstart += tls_get_record_body_alignment_offset(rl, recordstart);
recordstart = WPACKET_get_curr(thispkt) - len - headerlen;
if (rl->isdtls)
rechdrlen = dtls_get_rec_header_size(*recordstart);
else
rechdrlen = SSL3_RT_HEADER_LENGTH;
if (!dtls_crypt_sequence_number(rl->sn_enc_ctx, recordstart + DTLS1_RT_HEADER_SEQ_OFFS,
recordstart + DTLS1_RT_HEADER_LENGTH,
rl->sn_enc_offs)) {
if (rl->isdtls && DTLS13_UNI_HDR_FIX_BITS_IS_SET(*recordstart)) {
size_t seqnumlen = DTLS13_UNI_HDR_SEQ_BIT_IS_SET(*recordstart) ? 2 : 1;
if (!ossl_assert(DTLS13_UNI_HDR_SEQ_OFF + seqnumlen <= rechdrlen)
|| !dtls_crypt_sequence_number(rl->sn_enc_ctx, recordstart + DTLS13_UNI_HDR_SEQ_OFF,
seqnumlen, recordstart + rechdrlen,
rl->sn_enc_offs)) {
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
if (rl->msg_callback != NULL) {
unsigned char *recordstart;
const int version1_3 = rl->isdtls ? DTLS1_3_VERSION : TLS1_3_VERSION;
recordstart = WPACKET_get_curr(thispkt) - len - headerlen;
rl->msg_callback(1, thiswr->rec_version, SSL3_RT_HEADER, recordstart,
headerlen, rl->cbarg);
rechdrlen, rl->cbarg);
if (rl->version == version1_3 && rl->enc_ctx != NULL) {
unsigned char ctype = thistempl->type;
@ -1758,7 +1769,7 @@ int tls_post_encryption_processing_default(OSSL_RECORD_LAYER *rl,
return 0;
}
TLS_RL_RECORD_add_length(thiswr, headerlen);
TLS_RL_RECORD_add_length(thiswr, rechdrlen);
return 1;
}
@ -2017,6 +2028,22 @@ int tls_set1_bio(OSSL_RECORD_LAYER *rl, BIO *bio)
return 1;
}
size_t tls_get_record_header_len(OSSL_RECORD_LAYER *rl)
{
size_t headerlen;
if (rl->isdtls) {
if (rl->version == DTLS1_3_VERSION && rl->epoch > 0)
headerlen = DTLS13_UNI_HDR_FIXED_LENGTH;
else
headerlen = DTLS1_RT_HEADER_LENGTH;
} else {
headerlen = SSL3_RT_HEADER_LENGTH;
}
return headerlen;
}
/* Shared by most methods except tlsany_meth */
int tls_default_set_protocol_version(OSSL_RECORD_LAYER *rl, int version)
{

View file

@ -120,6 +120,21 @@ static void copy_flags(BIO *bio)
#define MSG_FRAG_LEN_MID 10
#define MSG_FRAG_LEN_LO 11
/* Returns true if the unified header fixed bits are set (rfc9147 section 4) */
#define DTLS13_UNI_HDR_FIX_BITS_IS_SET(byte) \
(((byte) & DTLS13_UNI_HDR_FIX_BITS_MASK) == DTLS13_UNI_HDR_FIX_BITS)
/* Returns true if the unified header connection id bit is set (rfc9147 section 4) */
#define DTLS13_UNI_HDR_CID_BIT_IS_SET(byte) \
(((byte) & DTLS13_UNI_HDR_CID_BIT) == DTLS13_UNI_HDR_CID_BIT)
/* Returns true if the unified header sequence number bit is set (rfc9147 section 4) */
#define DTLS13_UNI_HDR_SEQ_BIT_IS_SET(byte) \
(((byte) & DTLS13_UNI_HDR_SEQ_BIT) == DTLS13_UNI_HDR_SEQ_BIT)
/* Returns true if the unified header length bit is set (rfc9147 section 4) */
#define DTLS13_UNI_HDR_LEN_BIT_IS_SET(byte) \
(((byte) & DTLS13_UNI_HDR_LEN_BIT) == DTLS13_UNI_HDR_LEN_BIT)
static void dump_data(const char *data, int len)
{
@ -135,6 +150,9 @@ static void dump_data(const char *data, int len)
if (rem != len)
printf("*\n");
printf("*---- START OF RECORD ----\n");
/*
* TODO(DTLSv1.3): support variable length headers
*/
if (rem < DTLS1_RT_HEADER_LENGTH) {
printf("*---- RECORD TRUNCATED ----\n");
break;
@ -543,8 +561,22 @@ int mempacket_test_inject(BIO *bio, const char *in, int inl, int pktnum,
MEMPACKET *thispkt = NULL, *looppkt, *nextpkt, *allpkts[3];
int i, duprec;
const unsigned char *inu = (const unsigned char *)in;
size_t len = ((inu[RECORD_LEN_HI] << 8) | inu[RECORD_LEN_LO])
+ DTLS1_RT_HEADER_LENGTH;
size_t len;
if (DTLS13_UNI_HDR_FIX_BITS_IS_SET(*in)
/* The following code does not handle connection ids */
&& ossl_assert(!DTLS13_UNI_HDR_CID_BIT_IS_SET(*in))) {
if (DTLS13_UNI_HDR_LEN_BIT_IS_SET(*in)) {
len = 3; /* 2 bytes for len field and 1 byte for record type */
len += DTLS13_UNI_HDR_SEQ_BIT_IS_SET(*in) ? 2 : 1;
} else {
/* We assert that inl is the correct record length */
len = inl;
}
} else {
len = ((inu[RECORD_LEN_HI] << 8) | inu[RECORD_LEN_LO]);
len += DTLS1_RT_HEADER_LENGTH;
}
if (ctx == NULL)
return -1;

View file

@ -20,11 +20,15 @@ use constant TLS_RECORD_HEADER_LENGTH => 5;
#Record types
use constant {
RT_APPLICATION_DATA => 23,
RT_HANDSHAKE => 22,
RT_ALERT => 21,
RT_CCS => 20,
RT_UNKNOWN => 100
RT_APPLICATION_DATA => 23,
RT_HANDSHAKE => 22,
RT_ALERT => 21,
RT_CCS => 20,
RT_UNKNOWN => 100,
RT_DTLS_UNIHDR_EPOCH4 => 0x2c,
RT_DTLS_UNIHDR_EPOCH1 => 0x2d,
RT_DTLS_UNIHDR_EPOCH2 => 0x2e,
RT_DTLS_UNIHDR_EPOCH3 => 0x2f,
};
my %record_type = (
@ -32,7 +36,11 @@ my %record_type = (
RT_HANDSHAKE, "HANDSHAKE",
RT_ALERT, "ALERT",
RT_CCS, "CCS",
RT_UNKNOWN, "UNKNOWN"
RT_UNKNOWN, "UNKNOWN",
RT_DTLS_UNIHDR_EPOCH4, "DTLS UNIFIED HEADER (EPOCH 4)",
RT_DTLS_UNIHDR_EPOCH1, "DTLS UNIFIED HEADER (EPOCH 1)",
RT_DTLS_UNIHDR_EPOCH2, "DTLS UNIFIED HEADER (EPOCH 2)",
RT_DTLS_UNIHDR_EPOCH3, "DTLS UNIFIED HEADER (EPOCH 3)",
);
use constant {
@ -71,14 +79,12 @@ sub get_records
my $partial = "";
my @record_list = ();
my @message_list = ();
my $record_hdr_len = $isdtls ? DTLS_RECORD_HEADER_LENGTH
: TLS_RECORD_HEADER_LENGTH;
my $recnum = 1;
while (length ($packet) > 0) {
print " Record $recnum ", $server ? "(server -> client)\n"
: "(client -> server)\n";
my $record_hdr_len;
my $content_type;
my $version;
my $len;
@ -86,16 +92,56 @@ sub get_records
my $seq;
if ($isdtls) {
my $seqhi;
my $seqmi;
my $seqlo;
#Get the record header (unpack can't fail if $packet is too short)
($content_type, $version, $epoch,
$seqhi, $seqmi, $seqlo, $len) = unpack('Cnnnnnn', $packet);
$seq = ($seqhi << 32) | ($seqmi << 16) | $seqlo
my $isunifiedhdr;
$content_type = unpack('B[8]', $packet);
$isunifiedhdr = substr($content_type, 0, 3) == "001";
if ($isunifiedhdr == 1) {
my $cbit = substr($content_type, 3, 1);
my $sbit = substr($content_type, 4, 1);
my $lbit = substr($content_type, 5, 1);
my $eebits = substr($content_type, 6, 2);
if ($cbit == "1" || $lbit == "0") {
die("TLSProxy does not support variable DTLSv1.3 unified header bits");
}
# This is a unified header
if ($sbit == "1") {
($content_type, $seq, $len) = unpack('Cnn', $packet);
$record_hdr_len = 5;
} else {
($content_type, $seq, $len) = unpack('CCn', $packet);
$record_hdr_len = 4;
}
$version = VERS_DTLS_1_2; # DTLSv1.3 headers has DTLSv1.2 in its legacy_version field
if ($eebits == "00") {
$epoch = 4; # must be at least 4 since 0 epoch are not sent with unified hdr
} elsif ($eebits == "01") {
$epoch = 1;
} elsif ($eebits == "10") {
$epoch = 2;
} elsif ($eebits == "11") {
$epoch = 3;
} else {
die("Epoch bits is not 0's or 1's: should not happen")
}
} else {
my $seqhi;
my $seqmi;
my $seqlo;
#Get the record header (unpack can't fail if $packet is too short)
($content_type, $version, $epoch,
$seqhi, $seqmi, $seqlo, $len) = unpack('Cnnnnnn', $packet);
$seq = ($seqhi << 32) | ($seqmi << 16) | $seqlo;
$record_hdr_len = DTLS_RECORD_HEADER_LENGTH;
}
} else {
#Get the record header (unpack can't fail if $packet is too short)
($content_type, $version, $len) = unpack('Cnn', $packet);
$record_hdr_len = TLS_RECORD_HEADER_LENGTH;
}
if (length($packet) < $record_hdr_len + ($len // 0)) {
@ -295,7 +341,7 @@ sub init
orig_decrypt_data => $decrypt_data,
sent => 0,
encrypted => 0,
outer_content_type => RT_APPLICATION_DATA
outer_content_type => $content_type,
};
return bless $self, $class;
@ -397,11 +443,16 @@ sub reconstruct_record
my $content_type = (TLSProxy::Proxy->is_tls13() && $self->encrypted)
? $self->outer_content_type : $self->content_type;
if($self->{isdtls}) {
my $seqhi = ($self->seq >> 32) & 0xffff;
my $seqmi = ($self->seq >> 16) & 0xffff;
my $seqlo = ($self->seq >> 0) & 0xffff;
$data = pack('Cnnnnnn', $content_type, $self->version,
$self->epoch, $seqhi, $seqmi, $seqlo, $self->len);
if (TLSProxy::Proxy->is_tls13() && $self->encrypted) {
# Prepare a unified header
$data = pack('Cnn', $content_type, $self->seq, $self->len);
} else {
my $seqhi = ($self->seq >> 32) & 0xffff;
my $seqmi = ($self->seq >> 16) & 0xffff;
my $seqlo = ($self->seq >> 0) & 0xffff;
$data = pack('Cnnnnnn', $content_type, $self->version,
$self->epoch, $seqhi, $seqmi, $seqlo, $self->len);
}
} else {
$data = pack('Cnn', $content_type, $self->version,
$self->len);