[openssl] master update

Matt Caswell matt at openssl.org
Thu Oct 31 10:30:42 UTC 2019


The branch master has been updated
       via  f059e4cc435b7b850cfc8188d265a8925edff0bd (commit)
       via  1ca50aa975fb149a75a3b0411230761376cb5e33 (commit)
       via  712c0942939c9aba2f2afadb9e4276b1a3df1345 (commit)
       via  54f30cb57c78e5390d951e4a0c4d0bf2ce0d86a1 (commit)
       via  2111f5c2834a838c4fc1ca981fddf80cbc589dfc (commit)
      from  181ea366f67f46cab093d6a7bbb1b2f35125b9f2 (commit)


- Log -----------------------------------------------------------------
commit f059e4cc435b7b850cfc8188d265a8925edff0bd
Author: John Baldwin <jhb at FreeBSD.org>
Date:   Wed Oct 9 11:33:00 2019 -0700

    Don't generate a MAC when using KTLS.
    
    The kernel will generate the MAC when transmitting the frame.  Doing
    so here causes the MAC to be included as part of the plain text that
    the kernel MACs and encrypts.  Note that this path is not taken when
    using stitched cipher suites.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/10045)

commit 1ca50aa975fb149a75a3b0411230761376cb5e33
Author: John Baldwin <jhb at FreeBSD.org>
Date:   Fri Aug 23 16:42:48 2019 -0700

    Fix BIO_get_ktls_send() and BIO_get_ktls_recv() to work again.
    
    This partially reverts 3119ab3c9e6d211c461a245f3744893e17b6c193.  In the
    case of a simple openssl s_server instance, the bio in s->wbio is a
    BIO_TYPE_BUFFER BIO, not BIO_TYPE_SOCKET.  This caused all of the checks
    to fail breaking KTLS.
    
    The default return value of control methods I have looked it is zero
    for unknown control requests, so invoking the control requests should
    be returning 0 for non-socket BIOs already.
    
    This does still map the requests to 0 at compile time for the non-KTLS
    case so that the compiler can optimize the checks away entirely.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/10045)

commit 712c0942939c9aba2f2afadb9e4276b1a3df1345
Author: John Baldwin <jhb at FreeBSD.org>
Date:   Fri Aug 23 13:56:09 2019 -0700

    Simplify NO_KTLS path in SSL_sendfile.
    
    Avoid tripping over errno values from previous system calls in the
    thread and just hardcode the specific error.  BIO_get_ktls_send()
    should never be true in the NO_KTLS path, so the #ifdef could be
    moved even higher up to assume that error path in the NO_KTLS case
    instead.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/10045)

commit 54f30cb57c78e5390d951e4a0c4d0bf2ce0d86a1
Author: Andrew Gallatin <gallatin at gmail.com>
Date:   Wed Oct 31 15:01:47 2018 -0400

    Bypass multiblock and send individual records when using KTLS.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/10045)

commit 2111f5c2834a838c4fc1ca981fddf80cbc589dfc
Author: Andrew Gallatin <gallatin at gmail.com>
Date:   Mon Oct 22 11:02:19 2018 -0400

    Add support for in-kernel TLS (KTLS) on FreeBSD.
    
    - Check for the <sys/ktls.h> header to determine if KTLS support
      is available.
    - Populate a tls_enable structure with session key material for
      supported algorithms.  At present, AES-GCM128/256 and AES-CBC128/256
      with SHA1 and SHA2-256 HMACs are supported.  For AES-CBC, only MtE
      is supported.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/10045)

-----------------------------------------------------------------------

Summary of changes:
 Configure                 |  8 +++-
 crypto/bio/bss_sock.c     |  8 ++++
 include/internal/ktls.h   | 97 +++++++++++++++++++++++++++++++++++++++++++++++
 include/openssl/bio.h     |  6 +--
 ssl/record/rec_layer_s3.c |  3 +-
 ssl/ssl_lib.c             | 14 +++----
 ssl/t1_enc.c              | 45 +++++++++++++++++++++-
 7 files changed, 165 insertions(+), 16 deletions(-)

diff --git a/Configure b/Configure
index 6bba3aeeba..17d5fb5502 100755
--- a/Configure
+++ b/Configure
@@ -1586,8 +1586,14 @@ unless ($disabled{ktls}) {
         if ($verstr[2] < $minver) {
             disable('too-old-kernel', 'ktls');
         }
+    } elsif ($target =~ m/^BSD/) {
+        my $cc = $config{CROSS_COMPILE}.$config{CC};
+        system("printf '#include <sys/types.h>\n#include <sys/ktls.h>' | $cc -E - >/dev/null 2>&1");
+        if ($? != 0) {
+            disable('too-old-freebsd', 'ktls');
+        }
     } else {
-        disable('not-linux', 'ktls');
+        disable('not-linux-or-freebsd', 'ktls');
     }
 }
 
diff --git a/crypto/bio/bss_sock.c b/crypto/bio/bss_sock.c
index ed513495ff..09cc4e30a0 100644
--- a/crypto/bio/bss_sock.c
+++ b/crypto/bio/bss_sock.c
@@ -152,7 +152,11 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr)
     long ret = 1;
     int *ip;
 # ifndef OPENSSL_NO_KTLS
+#  ifdef __FreeBSD__
+    struct tls_enable *crypto_info;
+#  else
     struct tls12_crypto_info_aes_gcm_128 *crypto_info;
+#  endif
 # endif
 
     switch (cmd) {
@@ -183,7 +187,11 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr)
         break;
 # ifndef OPENSSL_NO_KTLS
     case BIO_CTRL_SET_KTLS:
+#  ifdef __FreeBSD__
+        crypto_info = (struct tls_enable *)ptr;
+#  else
         crypto_info = (struct tls12_crypto_info_aes_gcm_128 *)ptr;
+#  endif
         ret = ktls_start(b->num, crypto_info, sizeof(*crypto_info), num);
         if (ret)
             BIO_set_ktls_flag(b, num);
diff --git a/include/internal/ktls.h b/include/internal/ktls.h
index 9f2af1200c..209dff1689 100644
--- a/include/internal/ktls.h
+++ b/include/internal/ktls.h
@@ -11,6 +11,103 @@
 # ifndef HEADER_INTERNAL_KTLS
 #  define HEADER_INTERNAL_KTLS
 
+#  if defined(__FreeBSD__)
+#   include <sys/types.h>
+#   include <sys/socket.h>
+#   include <sys/ktls.h>
+#   include <netinet/in.h>
+#   include <netinet/tcp.h>
+#   include <crypto/cryptodev.h>
+
+/*
+ * Only used by the tests in sslapitest.c.
+ */
+#   define TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE             8
+
+/*
+ * FreeBSD does not require any additional steps to enable KTLS before
+ * setting keys.
+ */
+static ossl_inline int ktls_enable(int fd)
+{
+    return 1;
+}
+
+/*
+ * The TCP_TXTLS_ENABLE socket option marks the outgoing socket buffer
+ * as using TLS.  If successful, then data sent using this socket will
+ * be encrypted and encapsulated in TLS records using the tls_en.
+ * provided here.
+ */
+static ossl_inline int ktls_start(int fd,
+                                  struct tls_enable *tls_en,
+                                  size_t len, int is_tx)
+{
+    if (is_tx)
+        return setsockopt(fd, IPPROTO_TCP, TCP_TXTLS_ENABLE,
+                          tls_en, sizeof(*tls_en)) ? 0 : 1;
+    else
+        return 0;
+}
+
+/*
+ * Send a TLS record using the tls_en provided in ktls_start and use
+ * record_type instead of the default SSL3_RT_APPLICATION_DATA.
+ * When the socket is non-blocking, then this call either returns EAGAIN or
+ * the entire record is pushed to TCP. It is impossible to send a partial
+ * record using this control message.
+ */
+static ossl_inline int ktls_send_ctrl_message(int fd, unsigned char record_type,
+                                              const void *data, size_t length)
+{
+    struct msghdr msg = { 0 };
+    int cmsg_len = sizeof(record_type);
+    struct cmsghdr *cmsg;
+    char buf[CMSG_SPACE(cmsg_len)];
+    struct iovec msg_iov;   /* Vector of data to send/receive into */
+
+    msg.msg_control = buf;
+    msg.msg_controllen = sizeof(buf);
+    cmsg = CMSG_FIRSTHDR(&msg);
+    cmsg->cmsg_level = IPPROTO_TCP;
+    cmsg->cmsg_type = TLS_SET_RECORD_TYPE;
+    cmsg->cmsg_len = CMSG_LEN(cmsg_len);
+    *((unsigned char *)CMSG_DATA(cmsg)) = record_type;
+    msg.msg_controllen = cmsg->cmsg_len;
+
+    msg_iov.iov_base = (void *)data;
+    msg_iov.iov_len = length;
+    msg.msg_iov = &msg_iov;
+    msg.msg_iovlen = 1;
+
+    return sendmsg(fd, &msg, 0);
+}
+
+static ossl_inline int ktls_read_record(int fd, void *data, size_t length)
+{
+    return -1;
+}
+
+/*
+ * KTLS enables the sendfile system call to send data from a file over
+ * TLS.
+ */
+static ossl_inline ossl_ssize_t ktls_sendfile(int s, int fd, off_t off,
+                                              size_t size, int flags)
+{
+    off_t sbytes;
+    int ret;
+
+    ret = sendfile(fd, s, off, size, NULL, &sbytes, flags);
+    if (ret == -1) {
+	    if (errno == EAGAIN && sbytes != 0)
+		    return sbytes;
+	    return -1;
+    }
+    return sbytes;
+}
+#  endif                         /* __FreeBSD__ */
+
 #  if defined(OPENSSL_SYS_LINUX)
 #   include <linux/version.h>
 
diff --git a/include/openssl/bio.h b/include/openssl/bio.h
index 9fb8095014..bb289e6fa2 100644
--- a/include/openssl/bio.h
+++ b/include/openssl/bio.h
@@ -162,11 +162,9 @@ extern "C" {
 
 # ifndef OPENSSL_NO_KTLS
 #  define BIO_get_ktls_send(b)         \
-     (BIO_method_type(b) == BIO_TYPE_SOCKET \
-      && BIO_ctrl(b, BIO_CTRL_GET_KTLS_SEND, 0, NULL))
+     BIO_ctrl(b, BIO_CTRL_GET_KTLS_SEND, 0, NULL)
 #  define BIO_get_ktls_recv(b)         \
-     (BIO_method_type(b) == BIO_TYPE_SOCKET \
-      && BIO_ctrl(b, BIO_CTRL_GET_KTLS_RECV, 0, NULL))
+     BIO_ctrl(b, BIO_CTRL_GET_KTLS_RECV, 0, NULL)
 # else
 #  define BIO_get_ktls_send(b)  (0)
 #  define BIO_get_ktls_recv(b)  (0)
diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c
index 876e738a44..0b9d18fd00 100644
--- a/ssl/record/rec_layer_s3.c
+++ b/ssl/record/rec_layer_s3.c
@@ -426,6 +426,7 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, size_t len,
         len >= 4 * (max_send_fragment = ssl_get_max_send_fragment(s)) &&
         s->compress == NULL && s->msg_callback == NULL &&
         !SSL_WRITE_ETM(s) && SSL_USE_EXPLICIT_IV(s) &&
+        (BIO_get_ktls_send(s->wbio) == 0) &&
         EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx)) &
         EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK) {
         unsigned char aad[13];
@@ -985,7 +986,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
          * in the wb->buf
          */
 
-        if (!SSL_WRITE_ETM(s) && mac_size != 0) {
+        if (!BIO_get_ktls_send(s->wbio) && !SSL_WRITE_ETM(s) && mac_size != 0) {
             unsigned char *mac;
 
             if (!WPACKET_allocate_bytes(thispkt, mac_size, &mac)
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 794af76530..61c90218e3 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2061,11 +2061,11 @@ ossl_ssize_t SSL_sendfile(SSL *s, int fd, off_t offset, size_t size, int flags)
         return -1;
     }
 
-#ifndef OPENSSL_NO_KTLS
-    ret = ktls_sendfile(SSL_get_wfd(s), fd, offset, size, flags);
+#ifdef OPENSSL_NO_KTLS
+    ERR_raise_data(ERR_LIB_SYS, ERR_R_INTERNAL_ERROR, "calling sendfile()");
+    return -1;
 #else
-    ret = -1;
-#endif
+    ret = ktls_sendfile(SSL_get_wfd(s), fd, offset, size, flags);
     if (ret < 0) {
 #if defined(EAGAIN) && defined(EINTR) && defined(EBUSY)
         if ((get_last_sys_error() == EAGAIN) ||
@@ -2074,16 +2074,12 @@ ossl_ssize_t SSL_sendfile(SSL *s, int fd, off_t offset, size_t size, int flags)
             BIO_set_retry_write(s->wbio);
         else
 #endif
-#ifdef OPENSSL_NO_KTLS
-            ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
-                          "calling sendfile()");
-#else
             SSLerr(SSL_F_SSL_SENDFILE, SSL_R_UNINITIALIZED);
-#endif
         return ret;
     }
     s->rwstate = SSL_NOTHING;
     return ret;
+#endif
 }
 
 int SSL_write(SSL *s, const void *buf, int num)
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index 64806a333c..09bfb45884 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -151,11 +151,15 @@ int tls1_change_cipher_state(SSL *s, int which)
     size_t n, i, j, k, cl;
     int reuse_dd = 0;
 #ifndef OPENSSL_NO_KTLS
+# ifdef __FreeBSD__
+    struct tls_enable crypto_info;
+# else
     struct tls12_crypto_info_aes_gcm_128 crypto_info;
-    BIO *bio;
     unsigned char geniv[12];
     int count_unprocessed;
     int bit;
+# endif
+    BIO *bio;
 #endif
 
     c = s->s3.tmp.new_sym_enc;
@@ -387,6 +391,42 @@ int tls1_change_cipher_state(SSL *s, int which)
     if (ssl_get_max_send_fragment(s) != SSL3_RT_MAX_PLAIN_LENGTH)
         goto skip_ktls;
 
+# ifdef __FreeBSD__
+    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 = EVP_GCM_TLS_FIXED_IV_LEN;
+        break;
+    case SSL_AES128:
+    case SSL_AES256:
+        if (s->ext.use_etm)
+            goto skip_ktls;
+        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;
+        default:
+            goto skip_ktls;
+        }
+        crypto_info.cipher_algorithm = CRYPTO_AES_CBC;
+        crypto_info.iv_len = EVP_CIPHER_iv_length(c);
+        crypto_info.auth_key = ms;
+        crypto_info.auth_key_len = *mac_secret_size;
+        break;
+    default:
+        goto skip_ktls;
+    }
+    crypto_info.cipher_key = key;
+    crypto_info.cipher_key_len = EVP_CIPHER_key_length(c);
+    crypto_info.iv = iv;
+    crypto_info.tls_vmajor = (s->version >> 8) & 0x000000ff;
+    crypto_info.tls_vminor = (s->version & 0x000000ff);
+# else
     /* check that cipher is AES_GCM_128 */
     if (EVP_CIPHER_nid(c) != NID_aes_128_gcm
         || EVP_CIPHER_mode(c) != EVP_CIPH_GCM_MODE
@@ -396,6 +436,7 @@ int tls1_change_cipher_state(SSL *s, int which)
     /* check version is 1.2 */
     if (s->version != TLS1_2_VERSION)
         goto skip_ktls;
+# endif
 
     if (which & SSL3_CC_WRITE)
         bio = s->wbio;
@@ -422,6 +463,7 @@ int tls1_change_cipher_state(SSL *s, int which)
         goto err;
     }
 
+# ifndef __FreeBSD__
     memset(&crypto_info, 0, sizeof(crypto_info));
     crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_128;
     crypto_info.info.version = s->version;
@@ -455,6 +497,7 @@ int tls1_change_cipher_state(SSL *s, int which)
             count_unprocessed--;
         }
     }
+# endif
 
     /* ktls works with user provided buffers directly */
     if (BIO_set_ktls(bio, &crypto_info, which & SSL3_CC_WRITE)) {


More information about the openssl-commits mailing list