Skip to content

Commit

Permalink
DTLS 1.3 record number encryption
Browse files Browse the repository at this point in the history
  • Loading branch information
fwh-dc committed Aug 7, 2024
1 parent d85ea40 commit f4ea903
Show file tree
Hide file tree
Showing 22 changed files with 261 additions and 70 deletions.
2 changes: 2 additions & 0 deletions include/internal/recordmethod.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,14 @@ struct ossl_record_method_st {
uint16_t epoch,
unsigned char *secret,
size_t secretlen,
unsigned char *snkey,
unsigned char *key,
size_t keylen,
unsigned char *iv,
size_t ivlen,
unsigned char *mackey,
size_t mackeylen,
const EVP_CIPHER *snciph,
const EVP_CIPHER *ciph,
size_t taglen,
int mactype,
Expand Down
7 changes: 3 additions & 4 deletions ssl/d1_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -844,12 +844,11 @@ int DTLSv1_listen(SSL *ssl, BIO_ADDR *client)
* Reset the record layer - but this time we can use the record we just
* buffered in s->rlayer.rrlnext
*/
if (!ssl_set_new_record_layer(s,
DTLS_ANY_VERSION,
if (!ssl_set_new_record_layer(s, DTLS_ANY_VERSION,
OSSL_RECORD_DIRECTION_READ,
OSSL_RECORD_PROTECTION_LEVEL_NONE, NULL, 0,
NULL, 0, NULL, 0, NULL, 0, NULL, 0,
NID_undef, NULL, NULL, NULL)) {
NULL, NULL, 0, NULL, 0, NULL, 0, NULL, NULL,
0, NID_undef, NULL, NULL, NULL)) {
/* SSLfatal already called */
ret = -1;
goto end;
Expand Down
6 changes: 4 additions & 2 deletions ssl/quic/quic_tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,10 @@ static int
quic_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
int role, int direction, int level, uint16_t epoch,
unsigned char *secret, size_t secretlen,
unsigned char *key, size_t keylen, unsigned char *iv,
size_t ivlen, unsigned char *mackey, size_t mackeylen,
unsigned char *snkey, unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
const EVP_CIPHER *snciph,
const EVP_CIPHER *ciph, size_t taglen,
int mactype,
const EVP_MD *md, COMP_METHOD *comp,
Expand Down
60 changes: 55 additions & 5 deletions ssl/record/methods/dtls_meth.c
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,44 @@ static int dtls_retrieve_rlayer_buffered_record(OSSL_RECORD_LAYER *rl,
return 0;
}

/* rfc9147 section 4.2.3 */
int dtls_crypt_sequence_number(unsigned char *seq, size_t seq_len,
EVP_CIPHER_CTX *ctx, unsigned char *rec_data)
{
static const size_t mask_size = 16;
unsigned char mask[mask_size];
int outlen, inlen;
unsigned char *iv, *in;
const char *name = EVP_CIPHER_get0_name(EVP_CIPHER_CTX_get0_cipher(ctx));

memset(mask, 0, mask_size);

if (strncmp(name, "AES", 3) == 0) {
iv = NULL;
in = rec_data;
inlen = 16;
} else if (strncmp(name, "Cha", 3) == 0) {
iv = rec_data;
in = rec_data + 4;
inlen = 12;
} else {
return 0;
}

if (!ossl_assert(inlen >= 0)
|| (size_t)inlen > mask_size
|| seq_len > mask_size
|| EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, 1) <= 0
|| EVP_CipherUpdate(ctx, mask, &outlen, in, inlen) <= 0) {
return 0;
}

for (size_t i = 0; i < seq_len; i++)
seq[i] ^= mask[i];

return 1;
}

/*-
* Call this to get a new input record.
* It will return <= 0 if more data is needed, normally due to an error
Expand Down Expand Up @@ -445,6 +483,15 @@ int dtls_get_more_records(OSSL_RECORD_LAYER *rl)
rl->msg_callback(0, rr->rec_version, SSL3_RT_HEADER, rl->packet, DTLS1_RT_HEADER_LENGTH,
rl->cbarg);

if (rl->sn_enc_ctx != NULL
&& !dtls_crypt_sequence_number(&(rl->sequence[2]), 6,
rl->sn_enc_ctx, rl->packet + 13)) {
/* unexpected version, silently discard */
rr->length = 0;
rl->packet_length = 0;
goto again;
}

/*
* Lets check the version. We tolerate alerts that don't have the exact
* version number (e.g. because of protocol version errors)
Expand Down Expand Up @@ -628,8 +675,10 @@ static int
dtls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
int role, int direction, int level, uint16_t epoch,
unsigned char *secret, size_t secretlen,
unsigned char *key, size_t keylen, unsigned char *iv,
size_t ivlen, unsigned char *mackey, size_t mackeylen,
unsigned char *snkey, unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
const EVP_CIPHER *snciph,
const EVP_CIPHER *ciph, size_t taglen,
int mactype,
const EVP_MD *md, COMP_METHOD *comp,
Expand Down Expand Up @@ -683,9 +732,10 @@ dtls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
goto err;
}

ret = (*retrl)->funcs->set_crypto_state(*retrl, level, key, keylen, iv,
ivlen, mackey, mackeylen, ciph,
taglen, mactype, md, comp);
ret = (*retrl)->funcs->set_crypto_state(*retrl, level, snkey, key, keylen,
iv, ivlen, mackey, mackeylen,
snciph, ciph, taglen, mactype, md,
comp);

err:
if (ret != OSSL_RECORD_RETURN_SUCCESS) {
Expand Down
12 changes: 8 additions & 4 deletions ssl/record/methods/ktls_meth.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,9 +287,11 @@ int ktls_configure_crypto(OSSL_LIB_CTX *libctx, int version, const EVP_CIPHER *c
#endif /* OPENSSL_SYS_LINUX */

static int ktls_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
unsigned char *snkey,
unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
const EVP_CIPHER *snciph,
const EVP_CIPHER *ciph,
size_t taglen,
int mactype,
Expand Down Expand Up @@ -403,8 +405,10 @@ static int
ktls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
int role, int direction, int level, uint16_t epoch,
unsigned char *secret, size_t secretlen,
unsigned char *key, size_t keylen, unsigned char *iv,
size_t ivlen, unsigned char *mackey, size_t mackeylen,
unsigned char *snkey, unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
const EVP_CIPHER *snciph,
const EVP_CIPHER *ciph, size_t taglen,
int mactype,
const EVP_MD *md, COMP_METHOD *comp,
Expand All @@ -426,8 +430,8 @@ ktls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,

(*retrl)->funcs = &ossl_ktls_funcs;

ret = (*retrl)->funcs->set_crypto_state(*retrl, level, key, keylen, iv,
ivlen, mackey, mackeylen, ciph,
ret = (*retrl)->funcs->set_crypto_state(*retrl, level, snkey, key, keylen,
iv, ivlen, mackey, mackeylen, ciph,
taglen, mactype, md, comp);

if (ret != OSSL_RECORD_RETURN_SUCCESS) {
Expand Down
8 changes: 8 additions & 0 deletions ssl/record/methods/recmethod_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,11 @@ struct record_functions_st
* alternative record layer.
*/
int (*set_crypto_state)(OSSL_RECORD_LAYER *rl, int level,
unsigned char *snkey,
unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
const EVP_CIPHER *snciph,
const EVP_CIPHER *ciph,
size_t taglen,
int mactype,
Expand Down Expand Up @@ -298,6 +300,9 @@ struct ossl_record_layer_st
/* TLSv1.3 MAC ctx, only used with integrity-only cipher */
EVP_MAC_CTX *mac_ctx;

/* cryptographic state for DTLS sequence numbers */
EVP_CIPHER_CTX *sn_enc_ctx;

/* Explicit IV length */
size_t eivlen;

Expand Down Expand Up @@ -418,6 +423,9 @@ int tls_free_buffers(OSSL_RECORD_LAYER *rl);
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(unsigned char *seq, size_t seq_len,
EVP_CIPHER_CTX *ctx, unsigned char *rec_data);
int dtls_get_more_records(OSSL_RECORD_LAYER *rl);

int dtls_prepare_record_header(OSSL_RECORD_LAYER *rl,
Expand Down
2 changes: 2 additions & 0 deletions ssl/record/methods/ssl3_meth.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
#include "recmethod_local.h"

static int ssl3_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
unsigned char *snkey,
unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
const EVP_CIPHER *snciph,
const EVP_CIPHER *ciph,
size_t taglen,
int mactype,
Expand Down
20 changes: 20 additions & 0 deletions ssl/record/methods/tls13_meth.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
#include "recmethod_local.h"

static int tls13_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
unsigned char *snkey,
unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
const EVP_CIPHER *snciph,
const EVP_CIPHER *ciph,
size_t taglen,
int mactype,
Expand Down Expand Up @@ -78,6 +80,24 @@ static int tls13_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
return OSSL_RECORD_RETURN_FATAL;
}

if (rl->isdtls) {
EVP_CIPHER_CTX *sn_ciph_ctx;

sn_ciph_ctx = rl->sn_enc_ctx = EVP_CIPHER_CTX_new();

if (sn_ciph_ctx == NULL || snciph == NULL) {
ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
return OSSL_RECORD_RETURN_FATAL;
}

if (EVP_CipherInit_ex(sn_ciph_ctx, snciph, NULL,
snkey, NULL, 1) <= 0) {
ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
return OSSL_RECORD_RETURN_FATAL;
}
}

end:
return OSSL_RECORD_RETURN_SUCCESS;
}
Expand Down
2 changes: 2 additions & 0 deletions ssl/record/methods/tls1_meth.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
#include "recmethod_local.h"

static int tls1_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
unsigned char *snkey,
unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
const EVP_CIPHER *snciph,
const EVP_CIPHER *ciph,
size_t taglen,
int mactype,
Expand Down
25 changes: 20 additions & 5 deletions ssl/record/methods/tls_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1378,8 +1378,10 @@ static int
tls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
int role, int direction, int level, uint16_t epoch,
unsigned char *secret, size_t secretlen,
unsigned char *key, size_t keylen, unsigned char *iv,
size_t ivlen, unsigned char *mackey, size_t mackeylen,
unsigned char *snkey, unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
const EVP_CIPHER *snciph,
const EVP_CIPHER *ciph, size_t taglen,
int mactype,
const EVP_MD *md, COMP_METHOD *comp,
Expand Down Expand Up @@ -1421,9 +1423,10 @@ tls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
goto err;
}

ret = (*retrl)->funcs->set_crypto_state(*retrl, level, key, keylen, iv,
ivlen, mackey, mackeylen, ciph,
taglen, mactype, md, comp);
ret = (*retrl)->funcs->set_crypto_state(*retrl, level, snkey, key, keylen,
iv, ivlen, mackey, mackeylen,
snciph, ciph, taglen, mactype, md,
comp);

err:
if (ret != OSSL_RECORD_RETURN_SUCCESS) {
Expand Down Expand Up @@ -1711,6 +1714,18 @@ int tls_post_encryption_processing_default(OSSL_RECORD_LAYER *rl,
return 0;
}

if (rl->sn_enc_ctx != NULL) {
unsigned char *recordstart;

recordstart = WPACKET_get_curr(thispkt) - len - headerlen;

if (!dtls_crypt_sequence_number(recordstart + 5, 6, rl->sn_enc_ctx,
recordstart + 13)) {
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;
Expand Down
2 changes: 2 additions & 0 deletions ssl/record/methods/tlsany_meth.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
#define MIN_SSL2_RECORD_LEN 9

static int tls_any_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
unsigned char *snkey,
unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
const EVP_CIPHER *snciph,
const EVP_CIPHER *ciph,
size_t taglen,
int mactype,
Expand Down
18 changes: 11 additions & 7 deletions ssl/record/rec_layer_s3.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,16 @@ int RECORD_LAYER_reset(RECORD_LAYER *rl)
? DTLS_ANY_VERSION : TLS_ANY_VERSION,
OSSL_RECORD_DIRECTION_READ,
OSSL_RECORD_PROTECTION_LEVEL_NONE, NULL, 0,
NULL, 0, NULL, 0, NULL, 0, NULL, 0,
NID_undef, NULL, NULL, NULL);
NULL, NULL, 0, NULL, 0, NULL, 0, NULL, NULL,
0, NID_undef, NULL, NULL, NULL);

ret &= ssl_set_new_record_layer(rl->s,
SSL_CONNECTION_IS_DTLS(rl->s)
? DTLS_ANY_VERSION : TLS_ANY_VERSION,
OSSL_RECORD_DIRECTION_WRITE,
OSSL_RECORD_PROTECTION_LEVEL_NONE, NULL, 0,
NULL, 0, NULL, 0, NULL, 0, NULL, 0,
NID_undef, NULL, NULL, NULL);
NULL, NULL, 0, NULL, 0, NULL, 0, NULL, NULL,
0, NID_undef, NULL, NULL, NULL);

/* SSLfatal already called in the event of failure */
return ret;
Expand Down Expand Up @@ -1233,9 +1233,11 @@ static int ssl_post_record_layer_select(SSL_CONNECTION *s, int direction)
int ssl_set_new_record_layer(SSL_CONNECTION *s, int version,
int direction, int level,
unsigned char *secret, size_t secretlen,
unsigned char *snkey,
unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
const EVP_CIPHER *snciph,
const EVP_CIPHER *ciph, size_t taglen,
int mactype, const EVP_MD *md,
const SSL_COMP *comp, const EVP_MD *kdfdigest)
Expand Down Expand Up @@ -1409,9 +1411,11 @@ int ssl_set_new_record_layer(SSL_CONNECTION *s, int version,

rlret = meth->new_record_layer(sctx->libctx, sctx->propq, version,
s->server, direction, level, epoch,
secret, secretlen, key, keylen, iv,
ivlen, mackey, mackeylen, ciph, taglen,
mactype, md, compm, kdfdigest, prev,
secret, secretlen, snkey, key, keylen,
iv,
ivlen, mackey, mackeylen, snciph, ciph,
taglen, mactype, md, compm, kdfdigest,
prev,
thisbio, next, NULL, NULL, settings,
options, rlayer_dispatch_tmp, s,
s->rlayer.rlarg, &newrl);
Expand Down
2 changes: 2 additions & 0 deletions ssl/record/record.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,11 @@ int ossl_tls_handle_rlayer_return(SSL_CONNECTION *s, int writing, int ret,
int ssl_set_new_record_layer(SSL_CONNECTION *s, int version,
int direction, int level,
unsigned char *secret, size_t secretlen,
unsigned char *snkey,
unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
const EVP_CIPHER *snciph,
const EVP_CIPHER *ciph, size_t taglen,
int mactype, const EVP_MD *md,
const SSL_COMP *comp, const EVP_MD *kdfdigest);
Expand Down
Loading

0 comments on commit f4ea903

Please sign in to comment.