summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crypto/err/openssl.txt1
-rw-r--r--include/openssl/sslerr.h1
-rw-r--r--ssl/ktls.c113
-rw-r--r--ssl/record/methods/build.info4
-rw-r--r--ssl/record/methods/ktls_meth.c84
-rw-r--r--ssl/record/methods/recmethod_local.h1
-rw-r--r--ssl/record/methods/tls_common.c201
-rw-r--r--ssl/record/rec_layer_s3.c75
-rw-r--r--ssl/record/record.h5
-rw-r--r--ssl/record/recordmethod.h3
-rw-r--r--ssl/s3_enc.c4
-rw-r--r--ssl/ssl_err.c2
-rw-r--r--ssl/ssl_lib.c4
-rw-r--r--ssl/ssl_local.h9
-rw-r--r--ssl/t1_enc.c77
-rw-r--r--ssl/tls13_enc.c28
-rw-r--r--test/tls13secretstest.c5
17 files changed, 443 insertions, 174 deletions
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index b9f0f88f4f..8c0d2f4793 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -1434,6 +1434,7 @@ SSL_R_NO_SRTP_PROFILES:359:no srtp profiles
SSL_R_NO_SUITABLE_DIGEST_ALGORITHM:297:no suitable digest algorithm
SSL_R_NO_SUITABLE_GROUPS:295:no suitable groups
SSL_R_NO_SUITABLE_KEY_SHARE:101:no suitable key share
+SSL_R_NO_SUITABLE_RECORD_LAYER:322:no suitable record layer
SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM:118:no suitable signature algorithm
SSL_R_NO_VALID_SCTS:216:no valid scts
SSL_R_NO_VERIFY_COOKIE_CALLBACK:403:no verify cookie callback
diff --git a/include/openssl/sslerr.h b/include/openssl/sslerr.h
index 01a79ee48b..0e46b7b026 100644
--- a/include/openssl/sslerr.h
+++ b/include/openssl/sslerr.h
@@ -200,6 +200,7 @@
# define SSL_R_NO_SUITABLE_DIGEST_ALGORITHM 297
# define SSL_R_NO_SUITABLE_GROUPS 295
# define SSL_R_NO_SUITABLE_KEY_SHARE 101
+# define SSL_R_NO_SUITABLE_RECORD_LAYER 322
# define SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM 118
# define SSL_R_NO_VALID_SCTS 216
# define SSL_R_NO_VERIFY_COOKIE_CALLBACK 403
diff --git a/ssl/ktls.c b/ssl/ktls.c
index 78e6ecd554..602aa78e93 100644
--- a/ssl/ktls.c
+++ b/ssl/ktls.c
@@ -7,6 +7,7 @@
* https://www.openssl.org/source/license.html
*/
+#include <openssl/rand.h>
#include "ssl_local.h"
#include "internal/ktls.h"
@@ -81,7 +82,7 @@ static int check_rx_read_ahead(SSL_CONNECTION *s, unsigned char *rec_seq)
* supports the cipher suite used at all.
*/
int ktls_check_supported_cipher(const SSL_CONNECTION *s, const EVP_CIPHER *c,
- const EVP_CIPHER_CTX *dd)
+ size_t taglen)
{
switch (s->version) {
@@ -120,11 +121,10 @@ int ktls_check_supported_cipher(const SSL_CONNECTION *s, const EVP_CIPHER *c,
}
/* Function to configure kernel TLS structure */
-int ktls_configure_crypto(SSL_CONNECTION *s, const EVP_CIPHER *c,
- EVP_CIPHER_CTX *dd,
- void *rl_sequence, ktls_crypto_info_t *crypto_info,
- int is_tx, unsigned char *iv,
- unsigned char *key, unsigned char *mac_key,
+int ktls_configure_crypto(SSL_CONNECTION *s, const EVP_CIPHER *c, void *rl_sequence,
+ ktls_crypto_info_t *crypto_info, int is_tx,
+ unsigned char *iv, size_t ivlen, unsigned char *key,
+ size_t keylen, unsigned char *mac_key,
size_t mac_secret_size)
{
memset(crypto_info, 0, sizeof(*crypto_info));
@@ -132,20 +132,12 @@ int ktls_configure_crypto(SSL_CONNECTION *s, const EVP_CIPHER *c,
case SSL_AES128GCM:
case SSL_AES256GCM:
crypto_info->cipher_algorithm = CRYPTO_AES_NIST_GCM_16;
- if (s->version == TLS1_3_VERSION) {
- crypto_info->iv_len = EVP_CIPHER_CTX_get_iv_length(dd);
- if (crypto_info->iv_len < 0)
- return 0;
- }
- else
- crypto_info->iv_len = EVP_GCM_TLS_FIXED_IV_LEN;
+ crypto_info->iv_len = ivlen;
break;
# ifdef OPENSSL_KTLS_CHACHA20_POLY1305
case SSL_CHACHA20POLY1305:
crypto_info->cipher_algorithm = CRYPTO_CHACHA20_POLY1305;
- crypto_info->iv_len = EVP_CIPHER_CTX_get_iv_length(dd);
- if (crypto_info->iv_len < 0)
- return 0;
+ crypto_info->iv_len = ivlen;
break;
# endif
case SSL_AES128:
@@ -164,7 +156,7 @@ int ktls_configure_crypto(SSL_CONNECTION *s, const EVP_CIPHER *c,
return 0;
}
crypto_info->cipher_algorithm = CRYPTO_AES_CBC;
- crypto_info->iv_len = EVP_CIPHER_get_iv_length(c);
+ crypto_info->iv_len = ivlen;
crypto_info->auth_key = mac_key;
crypto_info->auth_key_len = mac_secret_size;
break;
@@ -172,7 +164,7 @@ int ktls_configure_crypto(SSL_CONNECTION *s, const EVP_CIPHER *c,
return 0;
}
crypto_info->cipher_key = key;
- crypto_info->cipher_key_len = EVP_CIPHER_get_key_length(c);
+ crypto_info->cipher_key_len = keylen;
crypto_info->iv = iv;
crypto_info->tls_vmajor = (s->version >> 8) & 0x000000ff;
crypto_info->tls_vminor = (s->version & 0x000000ff);
@@ -193,7 +185,7 @@ int ktls_configure_crypto(SSL_CONNECTION *s, const EVP_CIPHER *c,
/* Function to check supported ciphers in Linux */
int ktls_check_supported_cipher(const SSL_CONNECTION *s, const EVP_CIPHER *c,
- const EVP_CIPHER_CTX *dd)
+ size_t taglen)
{
switch (s->version) {
case TLS1_2_VERSION:
@@ -209,7 +201,7 @@ int ktls_check_supported_cipher(const SSL_CONNECTION *s, const EVP_CIPHER *c,
# ifdef OPENSSL_KTLS_AES_CCM_128
if (EVP_CIPHER_is_a(c, "AES-128-CCM")) {
if (s->version == TLS_1_3_VERSION /* broken on 5.x kernels */
- || EVP_CIPHER_CTX_get_tag_length(dd) != EVP_CCM_TLS_TAG_LEN)
+ || taglen != EVP_CCM_TLS_TAG_LEN)
return 0;
return 1;
} else
@@ -231,28 +223,44 @@ int ktls_check_supported_cipher(const SSL_CONNECTION *s, const EVP_CIPHER *c,
}
/* Function to configure kernel TLS structure */
-int ktls_configure_crypto(SSL_CONNECTION *s, const EVP_CIPHER *c,
- EVP_CIPHER_CTX *dd,
- void *rl_sequence, ktls_crypto_info_t *crypto_info,
- int is_tx, unsigned char *iv,
- unsigned char *key, unsigned char *mac_key,
+int ktls_configure_crypto(SSL_CONNECTION *s, const EVP_CIPHER *c, void *rl_sequence,
+ ktls_crypto_info_t *crypto_info, int is_tx,
+ unsigned char *iv, size_t ivlen, unsigned char *key,
+ size_t keylen, unsigned char *mac_key,
size_t mac_secret_size)
{
- unsigned char geniv[12];
- unsigned char *iiv = iv;
+ unsigned char geniv[EVP_GCM_TLS_EXPLICIT_IV_LEN];
+ unsigned char *eiv;
+ SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
# ifdef OPENSSL_NO_KTLS_RX
if (!is_tx)
return 0;
# endif
- if (s->version == TLS1_2_VERSION &&
- EVP_CIPHER_get_mode(c) == EVP_CIPH_GCM_MODE) {
- if (!EVP_CIPHER_CTX_get_updated_iv(dd, geniv,
- EVP_GCM_TLS_FIXED_IV_LEN
- + EVP_GCM_TLS_EXPLICIT_IV_LEN))
+ if (EVP_CIPHER_get_mode(c) == EVP_CIPH_GCM_MODE
+ || EVP_CIPHER_get_mode(c) == EVP_CIPH_CCM_MODE) {
+ if (!ossl_assert(EVP_GCM_TLS_FIXED_IV_LEN == EVP_CCM_TLS_FIXED_IV_LEN)
+ || !ossl_assert(EVP_GCM_TLS_EXPLICIT_IV_LEN
+ == EVP_CCM_TLS_EXPLICIT_IV_LEN))
return 0;
- iiv = geniv;
+ if (s->version == TLS1_2_VERSION) {
+ if (!ossl_assert(ivlen == EVP_GCM_TLS_FIXED_IV_LEN))
+ return 0;
+ if (is_tx) {
+ if (RAND_bytes_ex(sctx->libctx, geniv,
+ EVP_GCM_TLS_EXPLICIT_IV_LEN, 0) <= 0)
+ return 0;
+ } else {
+ memset(geniv, 0, EVP_GCM_TLS_EXPLICIT_IV_LEN);
+ }
+ eiv = geniv;
+ } else {
+ if (!ossl_assert(ivlen == EVP_GCM_TLS_FIXED_IV_LEN
+ + EVP_GCM_TLS_EXPLICIT_IV_LEN))
+ return 0;
+ eiv = iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE;
+ }
}
memset(crypto_info, 0, sizeof(*crypto_info));
@@ -260,13 +268,15 @@ int ktls_configure_crypto(SSL_CONNECTION *s, const EVP_CIPHER *c,
{
# ifdef OPENSSL_KTLS_AES_GCM_128
case NID_aes_128_gcm:
+ if (!ossl_assert(TLS_CIPHER_AES_GCM_128_SALT_SIZE == EVP_GCM_TLS_FIXED_IV_LEN)
+ || !ossl_assert(TLS_CIPHER_AES_GCM_128_IV_SIZE == EVP_GCM_TLS_EXPLICIT_IV_LEN))
+ return 0;
crypto_info->gcm128.info.cipher_type = TLS_CIPHER_AES_GCM_128;
crypto_info->gcm128.info.version = s->version;
crypto_info->tls_crypto_info_len = sizeof(crypto_info->gcm128);
- memcpy(crypto_info->gcm128.iv, iiv + EVP_GCM_TLS_FIXED_IV_LEN,
- TLS_CIPHER_AES_GCM_128_IV_SIZE);
- memcpy(crypto_info->gcm128.salt, iiv, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
- memcpy(crypto_info->gcm128.key, key, EVP_CIPHER_get_key_length(c));
+ memcpy(crypto_info->gcm128.iv, eiv, TLS_CIPHER_AES_GCM_128_IV_SIZE);
+ memcpy(crypto_info->gcm128.salt, iv, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
+ memcpy(crypto_info->gcm128.key, key, keylen);
memcpy(crypto_info->gcm128.rec_seq, rl_sequence,
TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
if (!is_tx && !check_rx_read_ahead(s, crypto_info->gcm128.rec_seq))
@@ -275,28 +285,33 @@ int ktls_configure_crypto(SSL_CONNECTION *s, const EVP_CIPHER *c,
# endif
# ifdef OPENSSL_KTLS_AES_GCM_256
case NID_aes_256_gcm:
+ if (!ossl_assert(TLS_CIPHER_AES_GCM_256_SALT_SIZE == EVP_GCM_TLS_FIXED_IV_LEN)
+ || !ossl_assert(TLS_CIPHER_AES_GCM_256_IV_SIZE == EVP_GCM_TLS_EXPLICIT_IV_LEN))
+ return 0;
crypto_info->gcm256.info.cipher_type = TLS_CIPHER_AES_GCM_256;
crypto_info->gcm256.info.version = s->version;
crypto_info->tls_crypto_info_len = sizeof(crypto_info->gcm256);
- memcpy(crypto_info->gcm256.iv, iiv + EVP_GCM_TLS_FIXED_IV_LEN,
- TLS_CIPHER_AES_GCM_256_IV_SIZE);
- memcpy(crypto_info->gcm256.salt, iiv, TLS_CIPHER_AES_GCM_256_SALT_SIZE);
- memcpy(crypto_info->gcm256.key, key, EVP_CIPHER_get_key_length(c));
+ memcpy(crypto_info->gcm256.iv, eiv, TLS_CIPHER_AES_GCM_256_IV_SIZE);
+ memcpy(crypto_info->gcm256.salt, iv, TLS_CIPHER_AES_GCM_256_SALT_SIZE);
+ memcpy(crypto_info->gcm256.key, key, keylen);
memcpy(crypto_info->gcm256.rec_seq, rl_sequence,
TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE);
if (!is_tx && !check_rx_read_ahead(s, crypto_info->gcm256.rec_seq))
return 0;
+
return 1;
# endif
# ifdef OPENSSL_KTLS_AES_CCM_128
case NID_aes_128_ccm:
+ if (!ossl_assert(TLS_CIPHER_AES_CCM_128_SALT_SIZE == EVP_CCM_TLS_FIXED_IV_LEN)
+ || !ossl_assert(TLS_CIPHER_AES_CCM_128_IV_SIZE == EVP_CCM_TLS_EXPLICIT_IV_LEN))
+ return 0;
crypto_info->ccm128.info.cipher_type = TLS_CIPHER_AES_CCM_128;
crypto_info->ccm128.info.version = s->version;
crypto_info->tls_crypto_info_len = sizeof(crypto_info->ccm128);
- memcpy(crypto_info->ccm128.iv, iiv + EVP_CCM_TLS_FIXED_IV_LEN,
- TLS_CIPHER_AES_CCM_128_IV_SIZE);
- memcpy(crypto_info->ccm128.salt, iiv, TLS_CIPHER_AES_CCM_128_SALT_SIZE);
- memcpy(crypto_info->ccm128.key, key, EVP_CIPHER_get_key_length(c));
+ memcpy(crypto_info->ccm128.iv, eiv, TLS_CIPHER_AES_CCM_128_IV_SIZE);
+ memcpy(crypto_info->ccm128.salt, iv, TLS_CIPHER_AES_CCM_128_SALT_SIZE);
+ memcpy(crypto_info->ccm128.key, key, keylen);
memcpy(crypto_info->ccm128.rec_seq, rl_sequence,
TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE);
if (!is_tx && !check_rx_read_ahead(s, crypto_info->ccm128.rec_seq))
@@ -305,13 +320,13 @@ int ktls_configure_crypto(SSL_CONNECTION *s, const EVP_CIPHER *c,
# endif
# ifdef OPENSSL_KTLS_CHACHA20_POLY1305
case NID_chacha20_poly1305:
+ if (!ossl_assert(ivlen == TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE))
+ return 0;
crypto_info->chacha20poly1305.info.cipher_type = TLS_CIPHER_CHACHA20_POLY1305;
crypto_info->chacha20poly1305.info.version = s->version;
crypto_info->tls_crypto_info_len = sizeof(crypto_info->chacha20poly1305);
- memcpy(crypto_info->chacha20poly1305.iv, iiv,
- TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE);
- memcpy(crypto_info->chacha20poly1305.key, key,
- EVP_CIPHER_get_key_length(c));
+ memcpy(crypto_info->chacha20poly1305.iv, iv, ivlen);
+ memcpy(crypto_info->chacha20poly1305.key, key, keylen);
memcpy(crypto_info->chacha20poly1305.rec_seq, rl_sequence,
TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE);
if (!is_tx
diff --git a/ssl/record/methods/build.info b/ssl/record/methods/build.info
index dfe7d9c808..162739259c 100644
--- a/ssl/record/methods/build.info
+++ b/ssl/record/methods/build.info
@@ -7,4 +7,8 @@ IF[{- !$disabled{'deprecated-3.0'} -}]
SHARED_SOURCE[../../../libssl]=ssl3_cbc.c
ENDIF
+IF[{- !$disabled{'ktls'} -}]
+ SOURCE[../../../libssl]=ktls_meth.c
+ENDIF
+
SOURCE[../../../providers/libdefault.a ../../../providers/libfips.a]=ssl3_cbc.c
diff --git a/ssl/record/methods/ktls_meth.c b/ssl/record/methods/ktls_meth.c
new file mode 100644
index 0000000000..18576cee26
--- /dev/null
+++ b/ssl/record/methods/ktls_meth.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/evp.h>
+#include <openssl/core_names.h>
+#include "../../ssl_local.h"
+#include "../record_local.h"
+#include "recmethod_local.h"
+
+/* TODO(RECLAYER): Handle OPENSSL_NO_COMP */
+static int ktls_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
+ unsigned char *key, size_t keylen,
+ unsigned char *iv, size_t ivlen,
+ unsigned char *mackey, size_t mackeylen,
+ const EVP_CIPHER *ciph,
+ size_t taglen,
+ /* TODO(RECLAYER): This probably should not be an int */
+ int mactype,
+ const EVP_MD *md,
+ const SSL_COMP *comp,
+ /* TODO(RECLAYER): Remove me */
+ SSL_CONNECTION *s)
+{
+ void *rl_sequence;
+ ktls_crypto_info_t crypto_info;
+
+ /* Check if we are suitable for KTLS */
+
+ if (comp != NULL)
+ return 0;
+
+ /* ktls supports only the maximum fragment size */
+ if (ssl_get_max_send_fragment(s) != SSL3_RT_MAX_PLAIN_LENGTH)
+ return 0;
+
+ /* check that cipher is supported */
+ if (!ktls_check_supported_cipher(s, ciph, taglen))
+ return 0;
+
+ /*
+ * TODO(RECLAYER): For the write side we need to add a check for
+ * use of s->record_padding_cb
+ */
+
+ /* All future data will get encrypted by ktls. Flush the BIO or skip ktls */
+ if (rl->direction == OSSL_RECORD_DIRECTION_WRITE) {
+ if (BIO_flush(rl->bio) <= 0)
+ return 0;
+ }
+
+ if (rl->direction == OSSL_RECORD_DIRECTION_WRITE)
+ rl_sequence = RECORD_LAYER_get_write_sequence(&s->rlayer);
+ else
+ rl_sequence = RECORD_LAYER_get_read_sequence(&s->rlayer);
+
+ if (!ktls_configure_crypto(s, ciph, rl_sequence, &crypto_info,
+ rl->direction == OSSL_RECORD_DIRECTION_WRITE,
+ iv, ivlen, key, keylen, mackey, mackeylen))
+ return 0;
+
+ if (!BIO_set_ktls(rl->bio, &crypto_info, rl->direction))
+ return 0;
+
+ return 1;
+}
+
+static int ktls_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *inrecs, size_t n_recs,
+ int sending, SSL_MAC_BUF *mac, size_t macsize,
+ /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s)
+{
+ return 1;
+}
+
+struct record_functions_st ossl_ktls_funcs = {
+ ktls_set_crypto_state,
+ ktls_cipher,
+ NULL
+};
diff --git a/ssl/record/methods/recmethod_local.h b/ssl/record/methods/recmethod_local.h
index ec4001587d..b5d1bc2305 100644
--- a/ssl/record/methods/recmethod_local.h
+++ b/ssl/record/methods/recmethod_local.h
@@ -113,6 +113,7 @@ struct ossl_record_layer_st
extern struct record_functions_st ssl_3_0_funcs;
extern struct record_functions_st tls_1_funcs;
extern struct record_functions_st tls_1_3_funcs;
+extern struct record_functions_st ossl_ktls_funcs;
extern struct record_functions_st tls_any_funcs;
void ossl_rlayer_fatal(OSSL_RECORD_LAYER *rl, int al, int reason,
diff --git a/ssl/record/methods/tls_common.c b/ssl/record/methods/tls_common.c
index b693fcf5db..5106224c6c 100644
--- a/ssl/record/methods/tls_common.c
+++ b/ssl/record/methods/tls_common.c
@@ -185,6 +185,11 @@ static int tls_read_n(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend,
return OSSL_RECORD_RETURN_NON_FATAL_ERR;
rb = &rl->rbuf;
+ /*
+ * TODO(RECLAYER): Once this function is only called from inside the rlayer
+ * directly, we can probably remove this since it is initialised in
+ * tls_get_more_records
+ */
if (rb->buf == NULL) {
if (!rlayer_setup_read_buffer(rl)) {
/* RLAYERfatal() already called */
@@ -421,6 +426,12 @@ static int tls_get_more_records(OSSL_RECORD_LAYER *rl,
rr = rl->rrec;
rbuf = &rl->rbuf;
+ if (rbuf->buf == NULL) {
+ if (!rlayer_setup_read_buffer(rl)) {
+ /* RLAYERfatal() already called */
+ return OSSL_RECORD_RETURN_FATAL;
+ }
+ }
max_recs = s->max_pipelines;
if (max_recs == 0)
@@ -1091,27 +1102,19 @@ static int tls_release_record(OSSL_RECORD_LAYER *rl, void *rechandle)
return OSSL_RECORD_RETURN_SUCCESS;
}
-static OSSL_RECORD_LAYER *tls_new_record_layer(OSSL_LIB_CTX *libctx,
- const char *propq, int vers,
- int role, int direction,
- int level, unsigned char *key,
- size_t keylen,
- unsigned char *iv,
- size_t ivlen,
- unsigned char *mackey,
- size_t mackeylen,
- const EVP_CIPHER *ciph,
- size_t taglen,
- /* TODO(RECLAYER): This probably should not be an int */
- int mactype,
- const EVP_MD *md,
- const SSL_COMP *comp,
- BIO *transport, BIO_ADDR *local,
- BIO_ADDR *peer,
- const OSSL_PARAM *settings,
- const OSSL_PARAM *options,
- /* TODO(RECLAYER): Remove me */
- SSL_CONNECTION *s)
+static OSSL_RECORD_LAYER *
+tls_int_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
+ int role, int direction, int level, unsigned char *key,
+ size_t keylen, unsigned char *iv, size_t ivlen,
+ unsigned char *mackey, size_t mackeylen,
+ const EVP_CIPHER *ciph, size_t taglen,
+ /* TODO(RECLAYER): This probably should not be an int */
+ int mactype,
+ const EVP_MD *md, const SSL_COMP *comp, BIO *transport,
+ BIO_ADDR *local, BIO_ADDR *peer,
+ const OSSL_PARAM *settings, const OSSL_PARAM *options,
+ /* TODO(RECLAYER): Remove me */
+ SSL_CONNECTION *s)
{
OSSL_RECORD_LAYER *rl = OPENSSL_zalloc(sizeof(*rl));
const OSSL_PARAM *p;
@@ -1173,6 +1176,37 @@ static OSSL_RECORD_LAYER *tls_new_record_layer(OSSL_LIB_CTX *libctx,
if (!tls_set1_bio(rl, transport))
goto err;
+ return rl;
+ err:
+ OPENSSL_free(rl);
+ return NULL;
+}
+
+static OSSL_RECORD_LAYER *
+tls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
+ int role, int direction, int level, unsigned char *key,
+ size_t keylen, unsigned char *iv, size_t ivlen,
+ unsigned char *mackey, size_t mackeylen,
+ const EVP_CIPHER *ciph, size_t taglen,
+ /* TODO(RECLAYER): This probably should not be an int */
+ int mactype,
+ const EVP_MD *md, const SSL_COMP *comp, BIO *transport,
+ BIO_ADDR *local, BIO_ADDR *peer,
+ const OSSL_PARAM *settings, const OSSL_PARAM *options,
+ /* TODO(RECLAYER): Remove me */
+ SSL_CONNECTION *s)
+{
+ OSSL_RECORD_LAYER *rl = tls_int_new_record_layer(libctx, propq, vers, role,
+ direction, level, key,
+ keylen, iv, ivlen, mackey,
+ mackeylen, ciph, taglen,
+ mactype, md, comp,
+ transport, local, peer,
+ settings, options, s);
+
+ if (rl == NULL)
+ return NULL;
+
switch (vers) {
case TLS_ANY_VERSION:
rl->funcs = &tls_any_funcs;
@@ -1196,45 +1230,37 @@ static OSSL_RECORD_LAYER *tls_new_record_layer(OSSL_LIB_CTX *libctx,
if (!rl->funcs->set_crypto_state(rl, level, key, keylen, iv, ivlen,
mackey, mackeylen, ciph, taglen,
- mactype, md, comp, s)) {
- /* RLAYERfatal already called */
+ mactype, md, comp, s))
goto err;
- }
return rl;
err:
+ /* TODO(RECLAYER): How do we distinguish between fatal and non-fatal errors? */
OPENSSL_free(rl);
return NULL;
}
-static OSSL_RECORD_LAYER *dtls_new_record_layer(OSSL_LIB_CTX *libctx,
- const char *propq, int vers,
- int role, int direction,
- int level, unsigned char *key,
- size_t keylen,
- unsigned char *iv,
- size_t ivlen,
- unsigned char *mackey,
- size_t mackeylen,
- const EVP_CIPHER *ciph,
- size_t taglen,
- /* TODO(RECLAYER): This probably should not be an int */
- int mactype,
- const EVP_MD *md,
- const SSL_COMP *comp,
- BIO *transport, BIO_ADDR *local,
- BIO_ADDR *peer,
- const OSSL_PARAM *settings,
- const OSSL_PARAM *options,
- /* TODO(RECLAYER): Remove me */
- SSL_CONNECTION *s)
+static OSSL_RECORD_LAYER *
+dtls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
+ int role, int direction, int level, unsigned char *key,
+ size_t keylen, unsigned char *iv, size_t ivlen,
+ unsigned char *mackey, size_t mackeylen,
+ const EVP_CIPHER *ciph, size_t taglen,
+ /* TODO(RECLAYER): This probably should not be an int */
+ int mactype,
+ const EVP_MD *md, const SSL_COMP *comp, BIO *transport,
+ BIO_ADDR *local, BIO_ADDR *peer,
+ const OSSL_PARAM *settings, const OSSL_PARAM *options,
+ /* TODO(RECLAYER): Remove me */
+ SSL_CONNECTION *s)
{
- OSSL_RECORD_LAYER *rl = tls_new_record_layer(libctx, propq, vers, role,
- direction, level, key, keylen,
- iv, ivlen, mackey, mackeylen,
- ciph, taglen, mactype, md,
- comp, transport, local, peer,
- settings, options, s);
+ OSSL_RECORD_LAYER *rl = tls_int_new_record_layer(libctx, propq, vers, role,
+ direction, level, key,
+ keylen, iv, ivlen, mackey,
+ mackeylen, ciph, taglen,
+ mactype, md, comp,
+ transport, local, peer,
+ settings, options, s);
if (rl == NULL)
return NULL;
@@ -1244,6 +1270,47 @@ static OSSL_RECORD_LAYER *dtls_new_record_layer(OSSL_LIB_CTX *libctx,
return rl;
}
+#ifndef OPENSSL_NO_KTLS
+static OSSL_RECORD_LAYER *
+ktls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
+ int role, int direction, int level, unsigned char *key,
+ size_t keylen, unsigned char *iv, size_t ivlen,
+ unsigned char *mackey, size_t mackeylen,
+ const EVP_CIPHER *ciph, size_t taglen,
+ /* TODO(RECLAYER): This probably should not be an int */
+ int mactype,
+ const EVP_MD *md, const SSL_COMP *comp, BIO *transport,
+ BIO_ADDR *local, BIO_ADDR *peer,
+ const OSSL_PARAM *settings, const OSSL_PARAM *options,
+ /* TODO(RECLAYER): Remove me */
+ SSL_CONNECTION *s)
+{
+ OSSL_RECORD_LAYER *rl = tls_int_new_record_layer(libctx, propq, vers, role,
+ direction, level, key,
+ keylen, iv, ivlen, mackey,
+ mackeylen, ciph, taglen,
+ mactype, md, comp,
+ transport, local, peer,
+ settings, options, s);
+
+ if (rl == NULL)
+ return NULL;
+
+ rl->funcs = &ossl_ktls_funcs;
+
+ if (!rl->funcs->set_crypto_state(rl, level, key, keylen, iv, ivlen,
+ mackey, mackeylen, ciph, taglen,
+ mactype, md, comp, s))
+ goto err;
+
+ return rl;
+ err:
+ /* TODO(RECLAYER): How do we distinguish between fatal and non-fatal errors? */
+ OPENSSL_free(rl);
+ return NULL;
+}
+#endif
+
static void tls_free(OSSL_RECORD_LAYER *rl)
{
/* TODO(RECLAYER): Cleanse sensitive fields */
@@ -1368,6 +1435,38 @@ const OSSL_RECORD_METHOD ossl_tls_record_method = {
tls_reset_packet_length
};
+#ifndef OPENSSL_NO_KTLS
+const OSSL_RECORD_METHOD ossl_ktls_record_method = {
+ ktls_new_record_layer,
+ tls_free,
+ tls_reset,
+ tls_unprocessed_read_pending,
+ tls_processed_read_pending,
+ tls_app_data_pending,
+ tls_write_pending,
+ tls_get_max_record_len,
+ tls_get_max_records,
+ tls_write_records,
+ tls_retry_write_records,
+ tls_read_record,
+ tls_release_record,
+ tls_get_alert_code,
+ tls_set1_bio,
+
+ /*
+ * TODO(RECLAYER): Remove these. These function pointers are temporary hacks
+ * during the record layer refactoring. They need to be removed before the
+ * refactor is complete.
+ */
+ tls_read_n,
+ tls_get0_rbuf,
+ tls_get0_packet,
+ tls_set0_packet,
+ tls_get_packet_length,
+ tls_reset_packet_length
+};
+#endif
+
const OSSL_RECORD_METHOD ossl_dtls_record_method = {
dtls_new_record_layer,
tls_free,
diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c
index 61a4316704..a9e0baa687 100644
--- a/ssl/record/rec_layer_s3.c
+++ b/ssl/record/rec_layer_s3.c
@@ -1750,8 +1750,44 @@ size_t RECORD_LAYER_get_rrec_length(RECORD_LAYER *rl)
return SSL3_RECORD_get_length(&rl->rrec[0]);
}
-int ssl_set_new_record_layer(SSL_CONNECTION *s, const OSSL_RECORD_METHOD *meth,
- int version, int direction, int level,
+static const OSSL_RECORD_METHOD *ssl_select_next_record_layer(SSL_CONNECTION *s,
+ int level)
+{
+
+ if (level == OSSL_RECORD_PROTECTION_LEVEL_NONE) {
+ if (SSL_CONNECTION_IS_DTLS(s))
+ return &ossl_dtls_record_method;
+
+ return &ossl_tls_record_method;
+ }
+
+#ifndef OPENSSL_NO_KTLS
+ /* KTLS does not support renegotiation */
+ if (level == OSSL_RECORD_PROTECTION_LEVEL_APPLICATION
+ && (s->options & SSL_OP_ENABLE_KTLS) != 0
+ && (SSL_CONNECTION_IS_TLS13(s) || SSL_IS_FIRST_HANDSHAKE(s)))
+ return &ossl_ktls_record_method;
+#endif
+
+ /* Default to the current OSSL_RECORD_METHOD */
+ return s->rrlmethod;
+}
+
+static int ssl_post_record_layer_select(SSL_CONNECTION *s)
+{
+#ifndef OPENSSL_NO_KTLS
+ SSL *ssl = SSL_CONNECTION_GET_SSL(s);
+
+ if (s->rrlmethod == &ossl_ktls_record_method) {
+ /* KTLS does not support renegotiation so disallow it */
+ SSL_set_options(ssl, SSL_OP_NO_RENEGOTIATION);
+ }
+#endif
+ return 1;
+}
+
+int ssl_set_new_record_layer(SSL_CONNECTION *s, int version,
+ int direction, int level,
unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
@@ -1761,8 +1797,12 @@ int ssl_set_new_record_layer(SSL_CONNECTION *s, const OSSL_RECORD_METHOD *meth,
{
OSSL_PARAM_BLD *tmpl = NULL;
OSSL_PARAM *options = NULL;
+ const OSSL_RECORD_METHOD *origmeth = s->rrlmethod;
int ret = 0;
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
+ const OSSL_RECORD_METHOD *meth;
+
+ meth = ssl_select_next_record_layer(s, level);
if (s->rrlmethod != NULL)
s->rrlmethod->free(s->rrl);
@@ -1790,18 +1830,29 @@ int ssl_set_new_record_layer(SSL_CONNECTION *s, const OSSL_RECORD_METHOD *meth,
goto err;
}
- s->rrl = s->rrlmethod->new_record_layer(sctx->libctx, sctx->propq,
- version, s->server, direction,
- level, key, keylen, iv, ivlen,
- mackey, mackeylen, ciph, taglen,
- mactype, md, comp, s->rbio,
- NULL, NULL, NULL, options, s);
- if (s->rrl == NULL) {
- ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
- goto err;
+ for (;;) {
+ s->rrl = s->rrlmethod->new_record_layer(sctx->libctx, sctx->propq,
+ version, s->server, direction,
+ level, key, keylen, iv, ivlen,
+ mackey, mackeylen, ciph, taglen,
+ mactype, md, comp, s->rbio,
+ NULL, NULL, NULL, options, s);
+ if (s->rrl == NULL) {
+ if (s->rrlmethod != origmeth && origmeth != NULL) {
+ /*
+ * We tried a new record layer method, but it didn't work out,
+ * so we fallback to the original method and try again
+ */
+ s->rrlmethod = origmeth;
+ continue;
+ }
+ ERR_raise(ERR_LIB_SSL, SSL_R_NO_SUITABLE_RECORD_LAYER);
+ goto err;
+ }
+ break;
}
- ret = 1;
+ ret = ssl_post_record_layer_select(s);
err:
OSSL_PARAM_free(options);
OSSL_PARAM_BLD_free(tmpl);
diff --git a/ssl/record/record.h b/ssl/record/record.h
index fb836716fa..39b44e1682 100644
--- a/ssl/record/record.h
+++ b/ssl/record/record.h
@@ -283,9 +283,8 @@ int dtls_buffer_listen_record(SSL_CONNECTION *s, size_t len, unsigned char *seq,
int ossl_tls_handle_rlayer_return(SSL_CONNECTION *s, int ret, char *file,
int line);
-int ssl_set_new_record_layer(SSL_CONNECTION *s, const OSSL_RECORD_METHOD *meth,
- int version, int direction, int level,
- unsigned char *key, size_t keylen,
+int ssl_set_new_record_layer(SSL_CONNECTION *s, int version, int direction,
+ int level, unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
const EVP_CIPHER *ciph, size_t taglen,
diff --git a/ssl/record/recordmethod.h b/ssl/record/recordmethod.h
index a14737836d..157b154805 100644
--- a/ssl/record/recordmethod.h
+++ b/ssl/record/recordmethod.h
@@ -294,6 +294,9 @@ struct ossl_record_method_st {
/* Standard built-in record methods */
extern const OSSL_RECORD_METHOD ossl_tls_record_method;
+# ifndef OPENSSL_NO_KTLS
+extern const OSSL_RECORD_METHOD ossl_ktls_record_method;
+# endif
extern const OSSL_RECORD_METHOD ossl_dtls_record_method;
#endif /* !defined(OSSL_INTERNAL_RECORDMETHOD_H) */
diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c
index bd66f300ef..fc9002b8e5 100644
--- a/ssl/s3_enc.c
+++ b/ssl/s3_enc.c
@@ -146,12 +146,12 @@ int ssl3_change_cipher_state(SSL_CONNECTION *s, int which)
}
if (which & SSL3_CC_READ) {
- if (!ssl_set_new_record_layer(s, NULL, SSL3_VERSION,
+ if (!ssl_set_new_record_layer(s, SSL3_VERSION,
OSSL_RECORD_DIRECTION_READ,
OSSL_RECORD_PROTECTION_LEVEL_APPLICATION,
key, key_len, iv, iv_len, mac_secret,
md_len, ciph, 0, NID_undef, md, comp)) {
- /* SSLfatal already called */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_NO_SUITABLE_RECORD_LAYER);
goto err;
}
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 8910b81952..7abd6de4a2 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -307,6 +307,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SUITABLE_GROUPS), "no suitable groups"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SUITABLE_KEY_SHARE),
"no suitable key share"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SUITABLE_RECORD_LAYER),
+ "no suitable record layer"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM),
"no suitable signature algorithm"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_VALID_SCTS), "no valid scts"},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index e076a27560..4688aaa327 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -663,14 +663,12 @@ int ossl_ssl_connection_reset(SSL *s)
* assign it.
*/
if (!ssl_set_new_record_layer(sc,
- SSL_CONNECTION_IS_DTLS(sc) ? &ossl_dtls_record_method
- : &ossl_tls_record_method,
TLS_ANY_VERSION,
OSSL_RECORD_DIRECTION_READ,
OSSL_RECORD_PROTECTION_LEVEL_NONE,
NULL, 0, NULL, 0, NULL, 0, NULL, 0,
NID_undef, NULL, NULL)) {
- /* SSLfatal already called */
+ SSLfatal(sc, SSL_AD_INTERNAL_ERROR, SSL_R_NO_SUITABLE_RECORD_LAYER);
return 0;
}
diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h
index 5648014f18..90fb9516ab 100644
--- a/ssl/ssl_local.h
+++ b/ssl/ssl_local.h
@@ -2860,13 +2860,12 @@ __owur int ssl_log_secret(SSL_CONNECTION *s, const char *label,
# ifndef OPENSSL_NO_KTLS
/* ktls.c */
int ktls_check_supported_cipher(const SSL_CONNECTION *s, const EVP_CIPHER *c,
- const EVP_CIPHER_CTX *dd);
+ size_t taglen);
int ktls_configure_crypto(SSL_CONNECTION *s, const EVP_CIPHER *c,
- EVP_CIPHER_CTX *dd,
void *rl_sequence, ktls_crypto_info_t *crypto_info,
- int is_tx, unsigned char *iv,
- unsigned char *key, unsigned char *mac_key,
- size_t mac_secret_size);
+ int is_tx, unsigned char *iv, size_t ivlen,
+ unsigned char *key, size_t keylen,
+ unsigned char *mac_key, size_t mac_secret_size);
# endif
__owur int srp_generate_server_master_secret(SSL_CONNECTION *s);
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index 6fee020f32..20964dfd61 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -165,6 +165,7 @@ int tls1_change_cipher_state(SSL_CONNECTION *s, int which)
EVP_MD_CTX *mac_ctx;
EVP_PKEY *mac_key;
size_t n, i, j, k, cl;
+ int iivlen;
int reuse_dd = 0;
#ifndef OPENSSL_NO_KTLS
ktls_crypto_info_t crypto_info;
@@ -172,6 +173,11 @@ int tls1_change_cipher_state(SSL_CONNECTION *s, int which)
BIO *bio;
#endif
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
+ /*
+ * Taglen is only relevant for CCM ciphersuites. Other ciphersuites
+ * ignore this value so we can default it to 0.
+ */
+ size_t taglen = 0;
c = s->s3.tmp.new_sym_enc;
m = s->s3.tmp.new_hash;
@@ -185,7 +191,12 @@ int tls1_change_cipher_state(SSL_CONNECTION *s, int which)
cl = EVP_CIPHER_get_key_length(c);
j = cl;
- k = tls_iv_length_within_key_block(c);
+ iivlen = tls_iv_length_within_key_block(c);
+ if (iivlen < 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ k = iivlen;
if ((which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||
(which == SSL3_CHANGE_CIPHER_SERVER_READ)) {
mac_secret = &(p[0]);
@@ -209,6 +220,14 @@ int tls1_change_cipher_state(SSL_CONNECTION *s, int which)
goto err;
}
+ if (EVP_CIPHER_get_mode(c) == EVP_CIPH_CCM_MODE) {
+ if ((s->s3.tmp.new_cipher->algorithm_enc
+ & (SSL_AES128CCM8 | SSL_AES256CCM8)) != 0)
+ taglen = EVP_CCM8_TLS_TAG_LEN;
+ else
+ taglen = EVP_CCM_TLS_TAG_LEN;
+ }
+
if (which & SSL3_CC_READ) {
if (SSL_CONNECTION_IS_DTLS(s)) {
if (s->ext.use_etm)
@@ -261,32 +280,18 @@ int tls1_change_cipher_state(SSL_CONNECTION *s, int which)
if (!SSL_CONNECTION_IS_DTLS(s))
RECORD_LAYER_reset_read_sequence(&s->rlayer);
} else {
- /*
- * Taglen is only relevant for CCM ciphersuites. Other ciphersuites
- * ignore this value so we can default it to 0.
- */
- size_t taglen = 0;
-
- if (EVP_CIPHER_get_mode(c) == EVP_CIPH_CCM_MODE) {
- if ((s->s3.tmp. new_cipher->algorithm_enc
- & (SSL_AES128CCM8 | SSL_AES256CCM8)) != 0)
- taglen = EVP_CCM8_TLS_TAG_LEN;
- else
- taglen = EVP_CCM_TLS_TAG_LEN;
- }
-
- if (!ssl_set_new_record_layer(s, NULL, s->version,
- OSSL_RECORD_DIRECTION_READ,
- OSSL_RECORD_PROTECTION_LEVEL_APPLICATION,
- key, cl, iv, (size_t)k, mac_secret,
- mac_secret_size, c, taglen, mac_type, m,
- comp)) {
- /* SSLfatal already called */
+ if (!ssl_set_new_record_layer(s, s->version,
+ OSSL_RECORD_DIRECTION_READ,
+ OSSL_RECORD_PROTECTION_LEVEL_APPLICATION,
+ key, cl, iv, (size_t)k, mac_secret,
+ mac_secret_size, c, taglen, mac_type,
+ m, comp)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_NO_SUITABLE_RECORD_LAYER);
goto err;
}
/* TODO(RECLAYER): Temporary - remove me */
- goto check_ktls;
+ goto skip_ktls;
}
} else {
s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
@@ -385,12 +390,6 @@ int tls1_change_cipher_state(SSL_CONNECTION *s, int which)
goto err;
}
} else if (EVP_CIPHER_get_mode(c) == EVP_CIPH_CCM_MODE) {
- int taglen;
- if (s->s3.tmp.
- new_cipher->algorithm_enc & (SSL_AES128CCM8 | SSL_AES256CCM8))
- taglen = EVP_CCM8_TLS_TAG_LEN;
- else
- taglen = EVP_CCM_TLS_TAG_LEN;
if (!EVP_CipherInit_ex(dd, c, NULL, NULL, NULL, (which & SSL3_CC_WRITE))
|| (EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_IVLEN, 12, NULL) <= 0)
|| (EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_TAG, taglen, NULL) <= 0)
@@ -419,7 +418,6 @@ int tls1_change_cipher_state(SSL_CONNECTION *s, int which)
goto err;
}
- check_ktls:
#ifndef OPENSSL_NO_KTLS
if (s->compress || (s->options & SSL_OP_ENABLE_KTLS) == 0)
goto skip_ktls;
@@ -429,7 +427,7 @@ int tls1_change_cipher_state(SSL_CONNECTION *s, int which)
goto skip_ktls;
/* check that cipher is supported */
- if (!ktls_check_supported_cipher(s, c, dd))
+ if (!ktls_check_supported_cipher(s, c, taglen))
goto skip_ktls;
if (which & SSL3_CC_WRITE)
@@ -460,9 +458,9 @@ int tls1_change_cipher_state(SSL_CONNECTION *s, int which)
else
rl_sequence = RECORD_LAYER_get_read_sequence(&s->rlayer);
- if (!ktls_configure_crypto(s, c, dd, rl_sequence, &crypto_info,
- which & SSL3_CC_WRITE, iv, key, mac_secret,
- mac_secret_size))
+ if (!ktls_configure_crypto(s, c, rl_sequence, &crypto_info,
+ which & SSL3_CC_WRITE, iv, (size_t)k, key, cl,
+ mac_secret, mac_secret_size))
goto skip_ktls;
/* ktls works with user provided buffers directly */
@@ -472,8 +470,8 @@ int tls1_change_cipher_state(SSL_CONNECTION *s, int which)
SSL_set_options(SSL_CONNECTION_GET_SSL(s), SSL_OP_NO_RENEGOTIATION);
}
- skip_ktls:
#endif /* OPENSSL_NO_KTLS */
+ skip_ktls:
s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
OSSL_TRACE_BEGIN(TLS) {
@@ -497,6 +495,7 @@ int tls1_setup_key_block(SSL_CONNECTION *s)
int mac_type = NID_undef;
size_t num, mac_secret_size = 0;
int ret = 0;
+ int ivlen;
if (s->s3.tmp.key_block_length != 0)
return 1;
@@ -515,8 +514,12 @@ int tls1_setup_key_block(SSL_CONNECTION *s)
s->s3.tmp.new_hash = hash;
s->s3.tmp.new_mac_pkey_type = mac_type;
s->s3.tmp.new_mac_secret_size = mac_secret_size;
- num = mac_secret_size + EVP_CIPHER_get_key_length(c)
- + tls_iv_length_within_key_block(c);
+ ivlen = tls_iv_length_within_key_block(c);
+ if (ivlen < 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ num = mac_secret_size + EVP_CIPHER_get_key_length(c) + ivlen;
num *= 2;
ssl3_cleanup_key_block(s);
diff --git a/ssl/tls13_enc.c b/ssl/tls13_enc.c
index 8ef0ca6981..d6069c492a 100644
--- a/ssl/tls13_enc.c
+++ b/ssl/tls13_enc.c
@@ -390,13 +390,20 @@ static int derive_secret_key_and_iv(SSL_CONNECTION *s, int sending,
else
*taglen = EVP_CCM_TLS_TAG_LEN;
} else {
+ int iivlen;
+
if (mode == EVP_CIPH_GCM_MODE) {
*taglen = EVP_GCM_TLS_TAG_LEN;
} else {
/* CHACHA20P-POLY1305 */
*taglen = EVP_CHACHAPOLY_TLS_TAG_LEN;
}
- *ivlen = EVP_CIPHER_get_iv_length(ciph);
+ iivlen = EVP_CIPHER_get_iv_length(ciph);
+ if (iivlen < 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
+ return 0;
+ }
+ *ivlen = iivlen;
}
if (!tls13_derive_key(s, md, secret, key, *keylen)
@@ -710,13 +717,15 @@ int tls13_change_cipher_state(SSL_CONNECTION *s, int which)
? OSSL_RECORD_PROTECTION_LEVEL_HANDSHAKE
: OSSL_RECORD_PROTECTION_LEVEL_APPLICATION);
- if (!ssl_set_new_record_layer(s, NULL, s->version,
+ if (!ssl_set_new_record_layer(s, s->version,
OSSL_RECORD_DIRECTION_READ,
level, key, keylen, iv, ivlen, NULL, 0,
cipher, taglen, NID_undef, NULL, NULL)) {
- /* SSLfatal already called */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_NO_SUITABLE_RECORD_LAYER);
goto err;
}
+ /* TODO(RECLAYER): Remove me */
+ goto skip_ktls;
}
#ifndef OPENSSL_NO_KTLS
@@ -734,7 +743,7 @@ int tls13_change_cipher_state(SSL_CONNECTION *s, int which)
goto skip_ktls;
/* check that cipher is supported */
- if (!ktls_check_supported_cipher(s, cipher, ciph_ctx))
+ if (!ktls_check_supported_cipher(s, cipher, taglen))
goto skip_ktls;
if (which & SSL3_CC_WRITE)
@@ -759,8 +768,9 @@ int tls13_change_cipher_state(SSL_CONNECTION *s, int which)
else
rl_sequence = RECORD_LAYER_get_read_sequence(&s->rlayer);
- if (!ktls_configure_crypto(s, cipher, ciph_ctx, rl_sequence, &crypto_info,
- which & SSL3_CC_WRITE, iv, key, NULL, 0))
+ if (!ktls_configure_crypto(s, cipher, rl_sequence, &crypto_info,
+ which & SSL3_CC_WRITE, iv, ivlen, key, keylen,
+ NULL, 0))
goto skip_ktls;
/* ktls works with user provided buffers directly */
@@ -768,9 +778,9 @@ int tls13_change_cipher_state(SSL_CONNECTION *s, int which)
if (which & SSL3_CC_WRITE)
ssl3_release_write_buffer(s);
}
-skip_ktls:
# endif
#endif
+skip_ktls:
ret = 1;
err:
if ((which & SSL3_CC_EARLY) != 0) {
@@ -826,13 +836,13 @@ int tls13_update_key(SSL_CONNECTION *s, int sending)
memcpy(insecret, secret, hashlen);
if (!sending) {
- if (!ssl_set_new_record_layer(s, NULL, s->version,
+ if (!ssl_set_new_record_layer(s, s->version,
OSSL_RECORD_DIRECTION_READ,
OSSL_RECORD_PROTECTION_LEVEL_APPLICATION,
key, keylen, iv, ivlen, NULL, 0,
s->s3.tmp.new_sym_enc, taglen, NID_undef, NULL,
NULL)) {
- /* SSLfatal already called */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_NO_SUITABLE_RECORD_LAYER);
goto err;
}
}
diff --git a/test/tls13secretstest.c b/test/tls13secretstest.c
index f8d14777b3..ae5702d3a6 100644
--- a/test/tls13secretstest.c
+++ b/test/tls13secretstest.c
@@ -225,9 +225,8 @@ void ssl_evp_md_free(const EVP_MD *md)
{
}
-int ssl_set_new_record_layer(SSL_CONNECTION *s, const OSSL_RECORD_METHOD *meth,
- int version, int direction, int level,
- unsigned char *key, size_t keylen,
+int ssl_set_new_record_layer(SSL_CONNECTION *s, int version, int direction,
+ int level, unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *mackey, size_t mackeylen,
const EVP_CIPHER *ciph, size_t taglen,