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:
parent
374768c6cf
commit
42d467380c
11 changed files with 477 additions and 136 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
29
ssl/d1_lib.c
29
ssl/d1_lib.c
|
@ -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. */
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue