Move ktls.c into the record layer
authorMatt Caswell <matt@openssl.org>
Thu, 12 May 2022 16:00:59 +0000 (17:00 +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)

ssl/build.info
ssl/ktls.c [deleted file]
ssl/record/methods/build.info
ssl/record/methods/ktls_meth.c

index 54fd9635498fb4cd1fd44b1cc71b986bf63b80cf..ea35779f07b10a874c45e72f07d4ad70b9dd7eb1 100644 (file)
@@ -6,11 +6,6 @@ IF[{- !$disabled{quic} -}]
   SUBDIRS=quic
 ENDIF
 
-$KTLSSRC=
-IF[{- !$disabled{ktls} -}]
-  $KTLSSRC=ktls.c
-ENDIF
-
 SOURCE[../libssl]=\
         pqueue.c time.c \
         statem/statem_srvr.c statem/statem_clnt.c  s3_lib.c  s3_enc.c \
@@ -24,7 +19,7 @@ SOURCE[../libssl]=\
         ssl_asn1.c ssl_txt.c ssl_init.c ssl_conf.c  ssl_mcnf.c \
         bio_ssl.c ssl_err.c ssl_err_legacy.c tls_srp.c t1_trce.c ssl_utst.c \
         statem/statem.c \
-        tls_depr.c $KTLSSRC
+        tls_depr.c
 
 # For shared builds we need to include the libcrypto packet.c and quic_vlint.c
 # in libssl as well.
diff --git a/ssl/ktls.c b/ssl/ktls.c
deleted file mode 100644 (file)
index 602aa78..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * Copyright 2018-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/rand.h>
-#include "ssl_local.h"
-#include "internal/ktls.h"
-
-#ifndef OPENSSL_NO_KTLS_RX
- /*
-  * Count the number of records that were not processed yet from record boundary.
-  *
-  * This function assumes that there are only fully formed records read in the
-  * record layer. If read_ahead is enabled, then this might be false and this
-  * function will fail.
-  */
-static int count_unprocessed_records(SSL_CONNECTION *s)
-{
-    SSL3_BUFFER *rbuf = s->rrlmethod->get0_rbuf(s->rrl);
-    PACKET pkt, subpkt;
-    int count = 0;
-
-    if (!PACKET_buf_init(&pkt, rbuf->buf + rbuf->offset, rbuf->left))
-        return -1;
-
-    while (PACKET_remaining(&pkt) > 0) {
-        /* Skip record type and version */
-        if (!PACKET_forward(&pkt, 3))
-            return -1;
-
-        /* Read until next record */
-        if (!PACKET_get_length_prefixed_2(&pkt, &subpkt))
-            return -1;
-
-        count += 1;
-    }
-
-    return count;
-}
-
-/*
- * The kernel cannot offload receive if a partial TLS record has been read.
- * Check the read buffer for unprocessed records.  If the buffer contains a
- * partial record, fail and return 0.  Otherwise, update the sequence
- * number at *rec_seq for the count of unprocessed records and return 1.
- */
-static int check_rx_read_ahead(SSL_CONNECTION *s, unsigned char *rec_seq)
-{
-    int bit, count_unprocessed;
-
-    count_unprocessed = count_unprocessed_records(s);
-    if (count_unprocessed < 0)
-        return 0;
-
-    /* increment the crypto_info record sequence */
-    while (count_unprocessed) {
-        for (bit = 7; bit >= 0; bit--) { /* increment */
-            ++rec_seq[bit];
-            if (rec_seq[bit] != 0)
-                break;
-        }
-        count_unprocessed--;
-
-    }
-
-    return 1;
-}
-#endif
-
-#if defined(__FreeBSD__)
-# include "crypto/cryptodev.h"
-
-/*-
- * Check if a given cipher is supported by the KTLS interface.
- * The kernel might still fail the setsockopt() if no suitable
- * provider is found, but this checks if the socket option
- * supports the cipher suite used at all.
- */
-int ktls_check_supported_cipher(const SSL_CONNECTION *s, const EVP_CIPHER *c,
-                                size_t taglen)
-{
-
-    switch (s->version) {
-    case TLS1_VERSION:
-    case TLS1_1_VERSION:
-    case TLS1_2_VERSION:
-    case TLS1_3_VERSION:
-        break;
-    default:
-        return 0;
-    }
-
-    switch (s->s3.tmp.new_cipher->algorithm_enc) {
-    case SSL_AES128GCM:
-    case SSL_AES256GCM:
-        return 1;
-# ifdef OPENSSL_KTLS_CHACHA20_POLY1305
-    case SSL_CHACHA20POLY1305:
-        return 1;
-# endif
-    case SSL_AES128:
-    case SSL_AES256:
-        if (s->ext.use_etm)
-            return 0;
-        switch (s->s3.tmp.new_cipher->algorithm_mac) {
-        case SSL_SHA1:
-        case SSL_SHA256:
-        case SSL_SHA384:
-            return 1;
-        default:
-            return 0;
-        }
-    default:
-        return 0;
-    }
-}
-
-/* Function to configure kernel TLS structure */
-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));
-    switch (s->s3.tmp.new_cipher->algorithm_enc) {
-    case SSL_AES128GCM:
-    case SSL_AES256GCM:
-        crypto_info->cipher_algorithm = CRYPTO_AES_NIST_GCM_16;
-        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 = ivlen;
-        break;
-# endif
-    case SSL_AES128:
-    case SSL_AES256:
-        switch (s->s3.tmp.new_cipher->algorithm_mac) {
-        case SSL_SHA1:
-            crypto_info->auth_algorithm = CRYPTO_SHA1_HMAC;
-            break;
-        case SSL_SHA256:
-            crypto_info->auth_algorithm = CRYPTO_SHA2_256_HMAC;
-            break;
-        case SSL_SHA384:
-            crypto_info->auth_algorithm = CRYPTO_SHA2_384_HMAC;
-            break;
-        default:
-            return 0;
-        }
-        crypto_info->cipher_algorithm = CRYPTO_AES_CBC;
-        crypto_info->iv_len = ivlen;
-        crypto_info->auth_key = mac_key;
-        crypto_info->auth_key_len = mac_secret_size;
-        break;
-    default:
-        return 0;
-    }
-    crypto_info->cipher_key = key;
-    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);
-# ifdef TCP_RXTLS_ENABLE
-    memcpy(crypto_info->rec_seq, rl_sequence, sizeof(crypto_info->rec_seq));
-    if (!is_tx && !check_rx_read_ahead(s, crypto_info->rec_seq))
-        return 0;
-# else
-    if (!is_tx)
-        return 0;
-# endif
-    return 1;
-};
-
-#endif                         /* __FreeBSD__ */
-
-#if defined(OPENSSL_SYS_LINUX)
-
-/* Function to check supported ciphers in Linux */
-int ktls_check_supported_cipher(const SSL_CONNECTION *s, const EVP_CIPHER *c,
-                                size_t taglen)
-{
-    switch (s->version) {
-    case TLS1_2_VERSION:
-    case TLS1_3_VERSION:
-        break;
-    default:
-        return 0;
-    }
-
-    /* check that cipher is AES_GCM_128, AES_GCM_256, AES_CCM_128 
-     * or Chacha20-Poly1305
-     */
-# 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 */
-            || taglen != EVP_CCM_TLS_TAG_LEN)
-            return 0;
-        return 1;
-    } else
-# endif
-    if (0
-# ifdef OPENSSL_KTLS_AES_GCM_128
-        || EVP_CIPHER_is_a(c, "AES-128-GCM")
-# endif
-# ifdef OPENSSL_KTLS_AES_GCM_256
-        || EVP_CIPHER_is_a(c, "AES-256-GCM")
-# endif
-# ifdef OPENSSL_KTLS_CHACHA20_POLY1305
-        || EVP_CIPHER_is_a(c, "ChaCha20-Poly1305")
-# endif
-        ) {
-        return 1;
-    }
-    return 0;
-}
-
-/* Function to configure kernel TLS structure */
-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[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 (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;
-        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));
-    switch (EVP_CIPHER_get_nid(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, 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))
-            return 0;
-        return 1;
-# 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, 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, 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))
-            return 0;
-        return 1;
-# 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, 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
-                && !check_rx_read_ahead(s,
-                                        crypto_info->chacha20poly1305.rec_seq))
-            return 0;
-        return 1;
-# endif
-    default:
-        return 0;
-    }
-
-}
-
-#endif /* OPENSSL_SYS_LINUX */
index 162739259cb8217183ba75ef8c6ff8d1acd64c97..2faecb138be2a2c7de2ab2a1219f0ec47590dd2c 100644 (file)
@@ -1,5 +1,11 @@
+$KTLSSRC=
+IF[{- !$disabled{ktls} -}]
+  $KTLSSRC=ktls_meth.c
+ENDIF
+
 SOURCE[../../../libssl]=\
-        tls_common.c ssl3_meth.c tls1_meth.c tls13_meth.c tlsany_meth.c
+        tls_common.c ssl3_meth.c tls1_meth.c tls13_meth.c tlsany_meth.c \
+        $KTLSSRC
 
 # For shared builds we need to include the sources needed in providers
 # (ssl3_cbc.c) in libssl as well.
@@ -7,8 +13,4 @@ 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
index 767e2ed74cf9b65d81c6300965498865f6b00185..b6c8aeeb5710a75f50ec61b13a495e7ef5628d65 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2018-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
@@ -9,9 +9,343 @@
 
 #include <openssl/evp.h>
 #include <openssl/core_names.h>
+#include <openssl/rand.h>
 #include "../../ssl_local.h"
 #include "../record_local.h"
 #include "recmethod_local.h"
+#include "internal/ktls.h"
+
+#ifndef OPENSSL_NO_KTLS_RX
+ /*
+  * Count the number of records that were not processed yet from record boundary.
+  *
+  * This function assumes that there are only fully formed records read in the
+  * record layer. If read_ahead is enabled, then this might be false and this
+  * function will fail.
+  */
+static int count_unprocessed_records(SSL_CONNECTION *s)
+{
+    SSL3_BUFFER *rbuf = s->rrlmethod->get0_rbuf(s->rrl);
+    PACKET pkt, subpkt;
+    int count = 0;
+
+    if (!PACKET_buf_init(&pkt, rbuf->buf + rbuf->offset, rbuf->left))
+        return -1;
+
+    while (PACKET_remaining(&pkt) > 0) {
+        /* Skip record type and version */
+        if (!PACKET_forward(&pkt, 3))
+            return -1;
+
+        /* Read until next record */
+        if (!PACKET_get_length_prefixed_2(&pkt, &subpkt))
+            return -1;
+
+        count += 1;
+    }
+
+    return count;
+}
+
+/*
+ * The kernel cannot offload receive if a partial TLS record has been read.
+ * Check the read buffer for unprocessed records.  If the buffer contains a
+ * partial record, fail and return 0.  Otherwise, update the sequence
+ * number at *rec_seq for the count of unprocessed records and return 1.
+ */
+static int check_rx_read_ahead(SSL_CONNECTION *s, unsigned char *rec_seq)
+{
+    int bit, count_unprocessed;
+
+    count_unprocessed = count_unprocessed_records(s);
+    if (count_unprocessed < 0)
+        return 0;
+
+    /* increment the crypto_info record sequence */
+    while (count_unprocessed) {
+        for (bit = 7; bit >= 0; bit--) { /* increment */
+            ++rec_seq[bit];
+            if (rec_seq[bit] != 0)
+                break;
+        }
+        count_unprocessed--;
+
+    }
+
+    return 1;
+}
+#endif
+
+#if defined(__FreeBSD__)
+# include "crypto/cryptodev.h"
+
+/*-
+ * Check if a given cipher is supported by the KTLS interface.
+ * The kernel might still fail the setsockopt() if no suitable
+ * provider is found, but this checks if the socket option
+ * supports the cipher suite used at all.
+ */
+int ktls_check_supported_cipher(const SSL_CONNECTION *s, const EVP_CIPHER *c,
+                                size_t taglen)
+{
+
+    switch (s->version) {
+    case TLS1_VERSION:
+    case TLS1_1_VERSION:
+    case TLS1_2_VERSION:
+    case TLS1_3_VERSION:
+        break;
+    default:
+        return 0;
+    }
+
+    switch (s->s3.tmp.new_cipher->algorithm_enc) {
+    case SSL_AES128GCM:
+    case SSL_AES256GCM:
+        return 1;
+# ifdef OPENSSL_KTLS_CHACHA20_POLY1305
+    case SSL_CHACHA20POLY1305:
+        return 1;
+# endif
+    case SSL_AES128:
+    case SSL_AES256:
+        if (s->ext.use_etm)
+            return 0;
+        switch (s->s3.tmp.new_cipher->algorithm_mac) {
+        case SSL_SHA1:
+        case SSL_SHA256:
+        case SSL_SHA384:
+            return 1;
+        default:
+            return 0;
+        }
+    default:
+        return 0;
+    }
+}
+
+/* Function to configure kernel TLS structure */
+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));
+    switch (s->s3.tmp.new_cipher->algorithm_enc) {
+    case SSL_AES128GCM:
+    case SSL_AES256GCM:
+        crypto_info->cipher_algorithm = CRYPTO_AES_NIST_GCM_16;
+        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 = ivlen;
+        break;
+# endif
+    case SSL_AES128:
+    case SSL_AES256:
+        switch (s->s3.tmp.new_cipher->algorithm_mac) {
+        case SSL_SHA1:
+            crypto_info->auth_algorithm = CRYPTO_SHA1_HMAC;
+            break;
+        case SSL_SHA256:
+            crypto_info->auth_algorithm = CRYPTO_SHA2_256_HMAC;
+            break;
+        case SSL_SHA384:
+            crypto_info->auth_algorithm = CRYPTO_SHA2_384_HMAC;
+            break;
+        default:
+            return 0;
+        }
+        crypto_info->cipher_algorithm = CRYPTO_AES_CBC;
+        crypto_info->iv_len = ivlen;
+        crypto_info->auth_key = mac_key;
+        crypto_info->auth_key_len = mac_secret_size;
+        break;
+    default:
+        return 0;
+    }
+    crypto_info->cipher_key = key;
+    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);
+# ifdef TCP_RXTLS_ENABLE
+    memcpy(crypto_info->rec_seq, rl_sequence, sizeof(crypto_info->rec_seq));
+    if (!is_tx && !check_rx_read_ahead(s, crypto_info->rec_seq))
+        return 0;
+# else
+    if (!is_tx)
+        return 0;
+# endif
+    return 1;
+};
+
+#endif                         /* __FreeBSD__ */
+
+#if defined(OPENSSL_SYS_LINUX)
+
+/* Function to check supported ciphers in Linux */
+int ktls_check_supported_cipher(const SSL_CONNECTION *s, const EVP_CIPHER *c,
+                                size_t taglen)
+{
+    switch (s->version) {
+    case TLS1_2_VERSION:
+    case TLS1_3_VERSION:
+        break;
+    default:
+        return 0;
+    }
+
+    /* check that cipher is AES_GCM_128, AES_GCM_256, AES_CCM_128
+     * or Chacha20-Poly1305
+     */
+# 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 */
+            || taglen != EVP_CCM_TLS_TAG_LEN)
+            return 0;
+        return 1;
+    } else
+# endif
+    if (0
+# ifdef OPENSSL_KTLS_AES_GCM_128
+        || EVP_CIPHER_is_a(c, "AES-128-GCM")
+# endif
+# ifdef OPENSSL_KTLS_AES_GCM_256
+        || EVP_CIPHER_is_a(c, "AES-256-GCM")
+# endif
+# ifdef OPENSSL_KTLS_CHACHA20_POLY1305
+        || EVP_CIPHER_is_a(c, "ChaCha20-Poly1305")
+# endif
+        ) {
+        return 1;
+    }
+    return 0;
+}
+
+/* Function to configure kernel TLS structure */
+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[EVP_GCM_TLS_EXPLICIT_IV_LEN];
+    unsigned char *eiv = NULL;
+    SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
+
+# ifdef OPENSSL_NO_KTLS_RX
+    if (!is_tx)
+        return 0;
+# endif
+
+    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;
+        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));
+    switch (EVP_CIPHER_get_nid(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, 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))
+            return 0;
+        return 1;
+# 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, 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, 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))
+            return 0;
+        return 1;
+# 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, 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
+                && !check_rx_read_ahead(s,
+                                        crypto_info->chacha20poly1305.rec_seq))
+            return 0;
+        return 1;
+# endif
+    default:
+        return 0;
+    }
+
+}
+
+#endif /* OPENSSL_SYS_LINUX */
 
 /* TODO(RECLAYER): Handle OPENSSL_NO_COMP */
 static int ktls_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,