]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Implement KTLS in the new read record layer code
authorMatt Caswell <matt@openssl.org>
Tue, 10 May 2022 17:50:00 +0000 (18:50 +0100)
committerMatt Caswell <matt@openssl.org>
Thu, 18 Aug 2022 15:38:12 +0000 (16:38 +0100)
Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/18132)

17 files changed:
crypto/err/openssl.txt
include/openssl/sslerr.h
ssl/ktls.c
ssl/record/methods/build.info
ssl/record/methods/ktls_meth.c [new file with mode: 0644]
ssl/record/methods/recmethod_local.h
ssl/record/methods/tls_common.c
ssl/record/rec_layer_s3.c
ssl/record/record.h
ssl/record/recordmethod.h
ssl/s3_enc.c
ssl/ssl_err.c
ssl/ssl_lib.c
ssl/ssl_local.h
ssl/t1_enc.c
ssl/tls13_enc.c
test/tls13secretstest.c

index b9f0f88f4fefb10a2cf3ffa02f5aeeeb33847a27..8c0d2f47936fb8a5930c70f3bff4d40078bf10ca 100644 (file)
@@ -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
index 01a79ee48be653184bdcf7442e772ad4f644ad18..0e46b7b02677f6f399a2e6723f30563cfd60d044 100644 (file)
 # 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
index 78e6ecd554b8bd073bc5899580e3c038da73375b..602aa78e93354c038e71af50972919ad784ba2a9 100644 (file)
@@ -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
index dfe7d9c808a62b68922eb90396d9ddb772e78a29..162739259cb8217183ba75ef8c6ff8d1acd64c97 100644 (file)
@@ -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 (file)
index 0000000..18576ce
--- /dev/null
@@ -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
+};
index ec4001587df9be547ce77ef3377b350b03208d2d..b5d1bc230549a866d588141255f391a4fe4fd107 100644 (file)
@@ -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,
index b693fcf5db2e098f6a5e52da4424599215a60351..5106224c6c93b876f796a62b3fe7b81519b167c2 100644 (file)
@@ -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,
index 61a4316704243553e33b242e778e832da5c0cdb1..a9e0baa687440ee100ed442345549bd3a1c462bf 100644 (file)
@@ -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);
index fb836716fa0af5ee5a370f1182f2117f3a38cd9c..39b44e1682e00c3bdb783faccdae1eac4c6262d5 100644 (file)
@@ -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,
index a14737836dbe143540bf572e55911be886d59b0a..157b154805a6be6ead7411c84165469d6d62f573 100644 (file)
@@ -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) */
index bd66f300ef07535832c26e2421b44a0bc4f55d56..fc9002b8e564f22db429ac2cdbf14df13003a878 100644 (file)
@@ -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;
         }
 
index 8910b819522921015b20610f98e51d3dfea3673f..7abd6de4a2430c65c4ff9eca309323f07b18dab7 100644 (file)
@@ -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"},
index e076a27560f113561326f527e795b667e80a5df0..4688aaa327c5bd28cc8ad424f03c4c464ba01978 100644 (file)
@@ -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;
     }
 
index 5648014f183272ab1447bd4cdc5a7b03c2bc4c3d..90fb9516abac6219a573775b0b6e49ef83c176b0 100644 (file)
@@ -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);
index 6fee020f32f433d561e033c68f435ae6da5a3ecf..20964dfd610417d274e82e8b57a15f6d8aa526e4 100644 (file)
@@ -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);
index 8ef0ca69818f058b6a0a4dd2b4bf7f4a28129023..d6069c492ad66aa95a58abb32018f26761a3caaa 100644 (file)
@@ -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;
         }
     }
index f8d14777b36170abd51ba3b57d91f891403fcfcb..ae5702d3a65bfeb4fce386afcca8999e2189b5a6 100644 (file)
@@ -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,