From owner-svn-ports-all@freebsd.org Sat May 23 19:35:44 2020 Return-Path: Delivered-To: svn-ports-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 56ED22DBE86; Sat, 23 May 2020 19:35:44 +0000 (UTC) (envelope-from brnrd@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 49Ttr01pWqz4Xcy; Sat, 23 May 2020 19:35:44 +0000 (UTC) (envelope-from brnrd@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 390E714DDE; Sat, 23 May 2020 19:35:44 +0000 (UTC) (envelope-from brnrd@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 04NJZiPt009852; Sat, 23 May 2020 19:35:44 GMT (envelope-from brnrd@FreeBSD.org) Received: (from brnrd@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 04NJZisa009850; Sat, 23 May 2020 19:35:44 GMT (envelope-from brnrd@FreeBSD.org) Message-Id: <202005231935.04NJZisa009850@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: brnrd set sender to brnrd@FreeBSD.org using -f From: Bernard Spil Date: Sat, 23 May 2020 19:35:43 +0000 (UTC) To: ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org Subject: svn commit: r536339 - in head/security/openssl: . files X-SVN-Group: ports-head X-SVN-Commit-Author: brnrd X-SVN-Commit-Paths: in head/security/openssl: . files X-SVN-Commit-Revision: 536339 X-SVN-Commit-Repository: ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-ports-all@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: SVN commit messages for the ports tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 23 May 2020 19:35:44 -0000 Author: brnrd Date: Sat May 23 19:35:43 2020 New Revision: 536339 URL: https://svnweb.freebsd.org/changeset/ports/536339 Log: security/openssl: Add kernel TLS option Submitted by: jhb@freebsd.org Differential Revision: https://reviews.freebsd.org/D24274 Added: head/security/openssl/files/extra-patch-ktls (contents, props changed) Modified: head/security/openssl/Makefile head/security/openssl/pkg-plist Modified: head/security/openssl/Makefile ============================================================================== --- head/security/openssl/Makefile Sat May 23 19:34:53 2020 (r536338) +++ head/security/openssl/Makefile Sat May 23 19:35:43 2020 (r536339) @@ -40,11 +40,13 @@ OPTIONS_GROUP_OPTIMIZE= ASM SSE2 THREADS OPTIONS_DEFINE_i386= I386 OPTIONS_GROUP_PROTOCOLS=NEXTPROTONEG SCTP SSL3 TLS1 TLS1_1 TLS1_2 -OPTIONS_DEFINE= ASYNC CT MAN3 RFC3779 SHARED ZLIB +OPTIONS_DEFINE= ASYNC CT KTLS MAN3 RFC3779 SHARED ZLIB OPTIONS_DEFAULT=ASM ASYNC CT GOST DES EC MAN3 MD4 NEXTPROTONEG RC2 RC4 \ RMD160 SCTP SHARED SSE2 THREADS TLS1 TLS1_1 TLS1_2 +OPTIONS_EXCLUDE=${${OSVERSION} < 1300042:?KTLS:} + OPTIONS_GROUP_OPTIMIZE_amd64= EC .if ${MACHINE_ARCH} == "amd64" @@ -66,6 +68,7 @@ GOST_DESC= GOST (Russian standard) HASHES_DESC= Hash Function Support I386_DESC= i386 (instead of i486+) IDEA_DESC= International Data Encryption Algorithm +KTLS_DESC= Kernel TLS offload MAN3_DESC= Install API manpages (section 3, 7) MD2_DESC= MD2 (obsolete) MD4_DESC= MD4 (unsafe) @@ -92,7 +95,7 @@ WEAK-SSL-CIPHERS_DESC= Weak cipher support (unsafe) ZLIB_DESC= zlib compression support # Upstream default disabled options -.for _option in md2 rc5 sctp ssl3 zlib weak-ssl-ciphers +.for _option in ktls md2 rc5 sctp ssl3 zlib weak-ssl-ciphers ${_option:tu}_CONFIGURE_ON= enable-${_option} .endfor @@ -108,6 +111,7 @@ TLS1_1_IMPLIES= TLS1_2 EC_CONFIGURE_ON= enable-ec_nistp_64_gcc_128 I386_CONFIGURE_ON= 386 +KTLS_EXTRA_PATCHES= ${FILESDIR}/extra-patch-ktls MAN3_EXTRA_PATCHES_OFF= ${FILESDIR}/extra-patch-util_process__docs.pl SHARED_MAKE_ENV= SHLIBVER=${OPENSSL_SHLIBVER} SHARED_PLIST_SUB= SHLIBVER=${OPENSSL_SHLIBVER} Added: head/security/openssl/files/extra-patch-ktls ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/security/openssl/files/extra-patch-ktls Sat May 23 19:35:43 2020 (r536339) @@ -0,0 +1,2567 @@ +diff --git CHANGES CHANGES +index f4230aaac0..3cc665f654 100644 +--- CHANGES ++++ CHANGES +@@ -306,6 +306,11 @@ + necessary to configure just to create a source distribution. + [Richard Levitte] + ++ *) Added support for Linux Kernel TLS data-path. The Linux Kernel data-path ++ improves application performance by removing data copies and providing ++ applications with zero-copy system calls such as sendfile and splice. ++ [Boris Pismenny] ++ + Changes between 1.1.1 and 1.1.1a [20 Nov 2018] + + *) Timing vulnerability in DSA signature generation +diff --git Configure Configure +index 2e9efaa5f3..524b58cbb9 100755 +--- Configure ++++ Configure +@@ -331,6 +331,7 @@ my @dtls = qw(dtls1 dtls1_2); + # For developers: keep it sorted alphabetically + + my @disablables = ( ++ "ktls", + "afalgeng", + "aria", + "asan", +@@ -464,6 +465,7 @@ our %disabled = ( # "what" => "comment" + "weak-ssl-ciphers" => "default", + "zlib" => "default", + "zlib-dynamic" => "default", ++ "ktls" => "default", + ); + + # Note: => pair form used for aesthetics, not to truly make a hash table +@@ -1567,6 +1569,33 @@ unless ($disabled{devcryptoeng}) { + } + } + ++unless ($disabled{ktls}) { ++ $config{ktls}=""; ++ if ($target =~ m/^linux/) { ++ my $usr = "/usr/$config{cross_compile_prefix}"; ++ chop($usr); ++ if ($config{cross_compile_prefix} eq "") { ++ $usr = "/usr"; ++ } ++ my $minver = (4 << 16) + (13 << 8) + 0; ++ my @verstr = split(" ",`cat $usr/include/linux/version.h | grep LINUX_VERSION_CODE`); ++ ++ if ($verstr[2] < $minver) { ++ disable('too-old-kernel', 'ktls'); ++ } ++ } elsif ($target =~ m/^BSD/) { ++ my $cc = $config{CROSS_COMPILE}.$config{CC}; ++ system("printf '#include \n#include ' | $cc -E - >/dev/null 2>&1"); ++ if ($? != 0) { ++ disable('too-old-freebsd', 'ktls'); ++ } ++ } else { ++ disable('not-linux-or-freebsd', 'ktls'); ++ } ++} ++ ++push @{$config{openssl_other_defines}}, "OPENSSL_NO_KTLS" if ($disabled{ktls}); ++ + # Get the extra flags used when building shared libraries and modules. We + # do this late because some of them depend on %disabled. + +diff --git INSTALL INSTALL +index 328ad2baf4..46735b8236 100644 +--- INSTALL ++++ INSTALL +@@ -262,6 +262,15 @@ + Don't build the AFALG engine. This option will be forced if + on a platform that does not support AFALG. + ++ enable-ktls ++ Build with Kernel TLS support. This option will enable the ++ use of the Kernel TLS data-path, which can improve ++ performance and allow for the use of sendfile and splice ++ system calls on TLS sockets. The Kernel may use TLS ++ accelerators if any are available on the system. ++ This option will be forced off on systems that do not support ++ the Kernel TLS data-path. ++ + enable-asan + Build with the Address sanitiser. This is a developer option + only. It may not work on all platforms and should never be +diff --git apps/s_client.c apps/s_client.c +index 26a6789d81..457e539b85 100644 +--- apps/s_client.c ++++ apps/s_client.c +@@ -3262,6 +3262,12 @@ static void print_stuff(BIO *bio, SSL *s, int full) + BIO_printf(bio, "Expansion: %s\n", + expansion ? SSL_COMP_get_name(expansion) : "NONE"); + #endif ++#ifndef OPENSSL_NO_KTLS ++ if (BIO_get_ktls_send(SSL_get_wbio(s))) ++ BIO_printf(bio_err, "Using Kernel TLS for sending\n"); ++ if (BIO_get_ktls_recv(SSL_get_rbio(s))) ++ BIO_printf(bio_err, "Using Kernel TLS for receiving\n"); ++#endif + + #ifdef SSL_DEBUG + { +diff --git apps/s_server.c apps/s_server.c +index 0ba75999fd..ddc0b4bcd7 100644 +--- apps/s_server.c ++++ apps/s_server.c +@@ -2923,6 +2923,12 @@ static void print_connection_info(SSL *con) + } + OPENSSL_free(exportedkeymat); + } ++#ifndef OPENSSL_NO_KTLS ++ if (BIO_get_ktls_send(SSL_get_wbio(con))) ++ BIO_printf(bio_err, "Using Kernel TLS for sending\n"); ++ if (BIO_get_ktls_recv(SSL_get_rbio(con))) ++ BIO_printf(bio_err, "Using Kernel TLS for receiving\n"); ++#endif + + (void)BIO_flush(bio_s_out); + } +diff --git crypto/bio/b_sock2.c crypto/bio/b_sock2.c +index 335dfabc61..80ef348d92 100644 +--- crypto/bio/b_sock2.c ++++ crypto/bio/b_sock2.c +@@ -12,6 +12,7 @@ + #include + + #include "bio_local.h" ++#include "internal/ktls.h" + + #include + +@@ -50,6 +51,17 @@ int BIO_socket(int domain, int socktype, int protocol, int options) + BIOerr(BIO_F_BIO_SOCKET, BIO_R_UNABLE_TO_CREATE_SOCKET); + return INVALID_SOCKET; + } ++# ifndef OPENSSL_NO_KTLS ++ { ++ /* ++ * The new socket is created successfully regardless of ktls_enable. ++ * ktls_enable doesn't change any functionality of the socket, except ++ * changing the setsockopt to enable the processing of ktls_start. ++ * Thus, it is not a problem to call it for non-TLS sockets. ++ */ ++ ktls_enable(sock); ++ } ++# endif + + return sock; + } +diff --git crypto/bio/bss_conn.c crypto/bio/bss_conn.c +index dd43a40601..3def4550cb 100644 +--- crypto/bio/bss_conn.c ++++ crypto/bio/bss_conn.c +@@ -11,6 +11,7 @@ + #include + + #include "bio_local.h" ++#include "internal/ktls.h" + + #ifndef OPENSSL_NO_SOCK + +@@ -20,6 +21,9 @@ typedef struct bio_connect_st { + char *param_hostname; + char *param_service; + int connect_mode; ++# ifndef OPENSSL_NO_KTLS ++ unsigned char record_type; ++# endif + + BIO_ADDRINFO *addr_first; + const BIO_ADDRINFO *addr_iter; +@@ -311,7 +315,12 @@ static int conn_read(BIO *b, char *out, int outl) + + if (out != NULL) { + clear_socket_error(); +- ret = readsocket(b->num, out, outl); ++# ifndef OPENSSL_NO_KTLS ++ if (BIO_get_ktls_recv(b)) ++ ret = ktls_read_record(b->num, out, outl); ++ else ++# endif ++ ret = readsocket(b->num, out, outl); + BIO_clear_retry_flags(b); + if (ret <= 0) { + if (BIO_sock_should_retry(ret)) +@@ -336,7 +345,16 @@ static int conn_write(BIO *b, const char *in, int inl) + } + + clear_socket_error(); +- ret = writesocket(b->num, in, inl); ++# ifndef OPENSSL_NO_KTLS ++ if (BIO_should_ktls_ctrl_msg_flag(b)) { ++ ret = ktls_send_ctrl_message(b->num, data->record_type, in, inl); ++ if (ret >= 0) { ++ ret = inl; ++ BIO_clear_ktls_ctrl_msg_flag(b); ++ } ++ } else ++# endif ++ ret = writesocket(b->num, in, inl); + BIO_clear_retry_flags(b); + if (ret <= 0) { + if (BIO_sock_should_retry(ret)) +@@ -352,6 +370,13 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr) + const char **pptr = NULL; + long ret = 1; + BIO_CONNECT *data; ++# ifndef OPENSSL_NO_KTLS ++# ifdef __FreeBSD__ ++ struct tls_enable *crypto_info; ++# else ++ struct tls12_crypto_info_aes_gcm_128 *crypto_info; ++# endif ++# endif + + data = (BIO_CONNECT *)b->ptr; + +@@ -500,6 +525,31 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr) + case BIO_CTRL_EOF: + ret = (b->flags & BIO_FLAGS_IN_EOF) != 0 ? 1 : 0; + 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); ++ break; ++ case BIO_CTRL_GET_KTLS_SEND: ++ return BIO_should_ktls_flag(b, 1); ++ case BIO_CTRL_GET_KTLS_RECV: ++ return BIO_should_ktls_flag(b, 0); ++ case BIO_CTRL_SET_KTLS_TX_SEND_CTRL_MSG: ++ BIO_set_ktls_ctrl_msg_flag(b); ++ data->record_type = num; ++ ret = 0; ++ break; ++ case BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG: ++ BIO_clear_ktls_ctrl_msg_flag(b); ++ ret = 0; ++ break; ++# endif + default: + ret = 0; + break; +diff --git crypto/bio/bss_sock.c crypto/bio/bss_sock.c +index 6251f3d46a..c879533fef 100644 +--- crypto/bio/bss_sock.c ++++ crypto/bio/bss_sock.c +@@ -11,6 +11,7 @@ + #include + #include "bio_local.h" + #include "internal/cryptlib.h" ++#include "internal/ktls.h" + + #ifndef OPENSSL_NO_SOCK + +@@ -64,6 +65,17 @@ BIO *BIO_new_socket(int fd, int close_flag) + if (ret == NULL) + return NULL; + BIO_set_fd(ret, fd, close_flag); ++# ifndef OPENSSL_NO_KTLS ++ { ++ /* ++ * The new socket is created successfully regardless of ktls_enable. ++ * ktls_enable doesn't change any functionality of the socket, except ++ * changing the setsockopt to enable the processing of ktls_start. ++ * Thus, it is not a problem to call it for non-TLS sockets. ++ */ ++ ktls_enable(fd); ++ } ++# endif + return ret; + } + +@@ -96,7 +108,12 @@ static int sock_read(BIO *b, char *out, int outl) + + if (out != NULL) { + clear_socket_error(); +- ret = readsocket(b->num, out, outl); ++# ifndef OPENSSL_NO_KTLS ++ if (BIO_get_ktls_recv(b)) ++ ret = ktls_read_record(b->num, out, outl); ++ else ++# endif ++ ret = readsocket(b->num, out, outl); + BIO_clear_retry_flags(b); + if (ret <= 0) { + if (BIO_sock_should_retry(ret)) +@@ -110,10 +127,20 @@ static int sock_read(BIO *b, char *out, int outl) + + static int sock_write(BIO *b, const char *in, int inl) + { +- int ret; ++ int ret = 0; + + clear_socket_error(); +- ret = writesocket(b->num, in, inl); ++# ifndef OPENSSL_NO_KTLS ++ if (BIO_should_ktls_ctrl_msg_flag(b)) { ++ unsigned char record_type = (intptr_t)b->ptr; ++ ret = ktls_send_ctrl_message(b->num, record_type, in, inl); ++ if (ret >= 0) { ++ ret = inl; ++ BIO_clear_ktls_ctrl_msg_flag(b); ++ } ++ } else ++# endif ++ ret = writesocket(b->num, in, inl); + BIO_clear_retry_flags(b); + if (ret <= 0) { + if (BIO_sock_should_retry(ret)) +@@ -126,6 +153,13 @@ 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) { + case BIO_C_SET_FD: +@@ -153,6 +187,31 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) + case BIO_CTRL_FLUSH: + ret = 1; + 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); ++ break; ++ case BIO_CTRL_GET_KTLS_SEND: ++ return BIO_should_ktls_flag(b, 1); ++ case BIO_CTRL_GET_KTLS_RECV: ++ return BIO_should_ktls_flag(b, 0); ++ case BIO_CTRL_SET_KTLS_TX_SEND_CTRL_MSG: ++ BIO_set_ktls_ctrl_msg_flag(b); ++ b->ptr = (void *)num; ++ ret = 0; ++ break; ++ case BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG: ++ BIO_clear_ktls_ctrl_msg_flag(b); ++ ret = 0; ++ break; ++# endif + case BIO_CTRL_EOF: + ret = (b->flags & BIO_FLAGS_IN_EOF) != 0 ? 1 : 0; + break; +diff --git crypto/err/openssl.txt crypto/err/openssl.txt +index 35512f9caf..426297da8b 100644 +--- crypto/err/openssl.txt ++++ crypto/err/openssl.txt +@@ -1315,6 +1315,7 @@ SSL_F_SSL_RENEGOTIATE:516:SSL_renegotiate + SSL_F_SSL_RENEGOTIATE_ABBREVIATED:546:SSL_renegotiate_abbreviated + SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT:320:* + SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT:321:* ++SSL_F_SSL_SENDFILE:639:SSL_sendfile + SSL_F_SSL_SESSION_DUP:348:ssl_session_dup + SSL_F_SSL_SESSION_NEW:189:SSL_SESSION_new + SSL_F_SSL_SESSION_PRINT_FP:190:SSL_SESSION_print_fp +diff --git crypto/evp/e_aes.c crypto/evp/e_aes.c +index 405ddbf9bf..4640c7528a 100644 +--- crypto/evp/e_aes.c ++++ crypto/evp/e_aes.c +@@ -2895,6 +2895,14 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) + memcpy(ptr, c->buf, arg); + return 1; + ++ case EVP_CTRL_GET_IV: ++ if (gctx->iv_gen != 1) ++ return 0; ++ if (gctx->ivlen != arg) ++ return 0; ++ memcpy(ptr, gctx->iv, arg); ++ return 1; ++ + case EVP_CTRL_GCM_SET_IV_FIXED: + /* Special case: -1 length restores whole IV */ + if (arg == -1) { +diff --git doc/man3/BIO_ctrl.pod doc/man3/BIO_ctrl.pod +index 60cd10883b..589338dd51 100644 +--- doc/man3/BIO_ctrl.pod ++++ doc/man3/BIO_ctrl.pod +@@ -5,7 +5,8 @@ + BIO_ctrl, BIO_callback_ctrl, BIO_ptr_ctrl, BIO_int_ctrl, BIO_reset, + BIO_seek, BIO_tell, BIO_flush, BIO_eof, BIO_set_close, BIO_get_close, + BIO_pending, BIO_wpending, BIO_ctrl_pending, BIO_ctrl_wpending, +-BIO_get_info_callback, BIO_set_info_callback, BIO_info_cb ++BIO_get_info_callback, BIO_set_info_callback, BIO_info_cb, BIO_get_ktls_send, ++BIO_get_ktls_recv + - BIO control operations + + =head1 SYNOPSIS +@@ -34,6 +35,9 @@ BIO_get_info_callback, BIO_set_info_callback, BIO_info_cb + int BIO_get_info_callback(BIO *b, BIO_info_cb **cbp); + int BIO_set_info_callback(BIO *b, BIO_info_cb *cb); + ++ int BIO_get_ktls_send(BIO *b); ++ int BIO_get_ktls_recv(BIO *b); ++ + =head1 DESCRIPTION + + BIO_ctrl(), BIO_callback_ctrl(), BIO_ptr_ctrl() and BIO_int_ctrl() +@@ -72,6 +76,11 @@ Not all BIOs support these calls. BIO_ctrl_pending() and BIO_ctrl_wpending() + return a size_t type and are functions, BIO_pending() and BIO_wpending() are + macros which call BIO_ctrl(). + ++BIO_get_ktls_send() returns 1 if the BIO is using the Kernel TLS data-path for ++sending. Otherwise, it returns zero. ++BIO_get_ktls_recv() returns 1 if the BIO is using the Kernel TLS data-path for ++receiving. Otherwise, it returns zero. ++ + =head1 RETURN VALUES + + BIO_reset() normally returns 1 for success and 0 or -1 for failure. File +@@ -92,6 +101,11 @@ BIO_get_close() returns the close flag value: BIO_CLOSE or BIO_NOCLOSE. + BIO_pending(), BIO_ctrl_pending(), BIO_wpending() and BIO_ctrl_wpending() + return the amount of pending data. + ++BIO_get_ktls_send() returns 1 if the BIO is using the Kernel TLS data-path for ++sending. Otherwise, it returns zero. ++BIO_get_ktls_recv() returns 1 if the BIO is using the Kernel TLS data-path for ++receiving. Otherwise, it returns zero. ++ + =head1 NOTES + + BIO_flush(), because it can write data may return 0 or -1 indicating +@@ -124,6 +138,11 @@ particular a return value of 0 can be returned if an operation is not + supported, if an error occurred, if EOF has not been reached and in + the case of BIO_seek() on a file BIO for a successful operation. + ++=head1 HISTORY ++ ++The BIO_get_ktls_send() and BIO_get_ktls_recv() functions were added in ++OpenSSL 3.0.0. ++ + =head1 COPYRIGHT + + Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. +diff --git doc/man3/SSL_CTX_set_mode.pod doc/man3/SSL_CTX_set_mode.pod +index 387d1ec1ef..373b2aa0f2 100644 +--- doc/man3/SSL_CTX_set_mode.pod ++++ doc/man3/SSL_CTX_set_mode.pod +@@ -114,6 +114,22 @@ enables this behaviour to allow interoperability with such broken + implementations. Please note that setting this option breaks interoperability + with correct implementations. This option only applies to DTLS over SCTP. + ++=item SSL_MODE_NO_KTLS_TX ++ ++Disable the use of the kernel TLS egress data-path. ++By default kernel TLS is enabled if it is supported by the negotiated ciphersuites ++and extensions and OpenSSL has been compiled with support for it. ++The kernel TLS data-path implements the record layer, ++and the crypto algorithm. The kernel will utilize the best hardware ++available for crypto. Using the kernel data-path should reduce the memory ++footprint of OpenSSL because no buffering is required. Also, the throughput ++should improve because data copy is avoided when user data is encrypted into ++kernel memory instead of the usual encrypt than copy to kernel. ++ ++Kernel TLS might not support all the features of OpenSSL. For instance, ++renegotiation, and setting the maximum fragment size is not possible as of ++Linux 4.20. ++ + =back + + All modes are off by default except for SSL_MODE_AUTO_RETRY which is on by +@@ -134,6 +150,7 @@ L, L + =head1 HISTORY + + SSL_MODE_ASYNC was added in OpenSSL 1.1.0. ++SSL_MODE_NO_KTLS_TX was first added to OpenSSL 3.0.0. + + =head1 COPYRIGHT + +diff --git doc/man3/SSL_write.pod doc/man3/SSL_write.pod +index a76ffbb8fd..d7900fd87b 100644 +--- doc/man3/SSL_write.pod ++++ doc/man3/SSL_write.pod +@@ -2,12 +2,13 @@ + + =head1 NAME + +-SSL_write_ex, SSL_write - write bytes to a TLS/SSL connection ++SSL_write_ex, SSL_write, SSL_sendfile - write bytes to a TLS/SSL connection + + =head1 SYNOPSIS + + #include + ++ ossl_ssize_t SSL_sendfile(SSL *s, int fd, off_t offset, size_t size, int flags); + int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written); + int SSL_write(SSL *ssl, const void *buf, int num); + +@@ -17,6 +18,14 @@ SSL_write_ex() and SSL_write() write B bytes from the buffer B into + the specified B connection. On success SSL_write_ex() will store the number + of bytes written in B<*written>. + ++SSL_sendfile() writes B bytes from offset B in the file ++descriptor B to the specified SSL connection B. This function provides ++efficient zero-copy semantics. SSL_sendfile() is available only when ++Kernel TLS is enabled, which can be checked by calling BIO_get_ktls_send(). ++It is provided here to allow users to maintain the same interface. ++The meaning of B is platform dependent. ++Currently, under Linux it is ignored. ++ + =head1 NOTES + + In the paragraphs below a "write function" is defined as one of either +@@ -104,17 +113,35 @@ You should instead call SSL_get_error() to find out if it's retryable. + + =back + ++For SSL_sendfile(), the following return values can occur: ++ ++=over 4 ++ ++=item Z<>>= 0 ++ ++The write operation was successful, the return value is the number ++of bytes of the file written to the TLS/SSL connection. ++ ++=item E 0 ++ ++The write operation was not successful, because either the connection was ++closed, an error occured or action must be taken by the calling process. ++Call SSL_get_error() with the return value to find out the reason. ++ ++=back ++ + =head1 SEE ALSO + + L, L, L + L, L, + L, L +-L, ++L, L, + L, L + + =head1 HISTORY + + The SSL_write_ex() function was added in OpenSSL 1.1.1. ++The SSL_sendfile() function was added in OpenSSL 3.0.0. + + =head1 COPYRIGHT + +diff --git engines/e_afalg.c engines/e_afalg.c +index 4b17228461..5ef3a8d457 100644 +--- engines/e_afalg.c ++++ engines/e_afalg.c +@@ -407,7 +407,7 @@ static int afalg_start_cipher_sk(afalg_ctx *actx, const unsigned char *in, + size_t inl, const unsigned char *iv, + unsigned int enc) + { +- struct msghdr msg = { 0 }; ++ struct msghdr msg; + struct cmsghdr *cmsg; + struct iovec iov; + ssize_t sbytes; +@@ -416,6 +416,7 @@ static int afalg_start_cipher_sk(afalg_ctx *actx, const unsigned char *in, + # endif + char cbuf[CMSG_SPACE(ALG_IV_LEN(ALG_AES_IV_LEN)) + CMSG_SPACE(ALG_OP_LEN)]; + ++ memset(&msg, 0, sizeof(msg)); + memset(cbuf, 0, sizeof(cbuf)); + msg.msg_control = cbuf; + msg.msg_controllen = sizeof(cbuf); +diff --git include/internal/bio.h include/internal/bio.h +index c343b27629..521b5fa219 100644 +--- include/internal/bio.h ++++ include/internal/bio.h +@@ -7,6 +7,9 @@ + * https://www.openssl.org/source/license.html + */ + ++#ifndef HEADER_INTERNAL_BIO_H ++# define HEADER_INTERNAL_BIO_H ++ + #include + + struct bio_method_st { +@@ -31,3 +34,39 @@ void bio_cleanup(void); + /* Old style to new style BIO_METHOD conversion functions */ + int bwrite_conv(BIO *bio, const char *data, size_t datal, size_t *written); + int bread_conv(BIO *bio, char *data, size_t datal, size_t *read); ++ ++/* Changes to these internal BIOs must also update include/openssl/bio.h */ ++# define BIO_CTRL_SET_KTLS 72 ++# define BIO_CTRL_SET_KTLS_TX_SEND_CTRL_MSG 74 ++# define BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG 75 ++ ++/* ++ * This is used with socket BIOs: ++ * BIO_FLAGS_KTLS_TX means we are using ktls with this BIO for sending. ++ * BIO_FLAGS_KTLS_TX_CTRL_MSG means we are about to send a ctrl message next. ++ * BIO_FLAGS_KTLS_RX means we are using ktls with this BIO for receiving. ++ */ ++# define BIO_FLAGS_KTLS_TX 0x800 ++# define BIO_FLAGS_KTLS_TX_CTRL_MSG 0x1000 ++# define BIO_FLAGS_KTLS_RX 0x2000 ++ ++/* KTLS related controls and flags */ ++# define BIO_set_ktls_flag(b, is_tx) \ ++ BIO_set_flags(b, (is_tx) ? BIO_FLAGS_KTLS_TX : BIO_FLAGS_KTLS_RX) ++# define BIO_should_ktls_flag(b, is_tx) \ ++ BIO_test_flags(b, (is_tx) ? BIO_FLAGS_KTLS_TX : BIO_FLAGS_KTLS_RX) ++# define BIO_set_ktls_ctrl_msg_flag(b) \ ++ BIO_set_flags(b, BIO_FLAGS_KTLS_TX_CTRL_MSG) ++# define BIO_should_ktls_ctrl_msg_flag(b) \ ++ BIO_test_flags(b, BIO_FLAGS_KTLS_TX_CTRL_MSG) ++# define BIO_clear_ktls_ctrl_msg_flag(b) \ ++ BIO_clear_flags(b, BIO_FLAGS_KTLS_TX_CTRL_MSG) ++ ++# define BIO_set_ktls(b, keyblob, is_tx) \ ++ BIO_ctrl(b, BIO_CTRL_SET_KTLS, is_tx, keyblob) ++# define BIO_set_ktls_ctrl_msg(b, record_type) \ ++ BIO_ctrl(b, BIO_CTRL_SET_KTLS_TX_SEND_CTRL_MSG, record_type, NULL) ++# define BIO_clear_ktls_ctrl_msg(b) \ ++ BIO_ctrl(b, BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG, 0, NULL) ++ ++#endif +diff --git include/internal/ktls.h include/internal/ktls.h +new file mode 100644 +index 0000000000..209dff1689 +--- /dev/null ++++ include/internal/ktls.h +@@ -0,0 +1,345 @@ ++/* ++ * Copyright 2018 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 ++ */ ++ ++#ifndef OPENSSL_NO_KTLS ++# ifndef HEADER_INTERNAL_KTLS ++# define HEADER_INTERNAL_KTLS ++ ++# if defined(__FreeBSD__) ++# include ++# include ++# include ++# include ++# include ++# include ++ ++/* ++ * 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 ++ ++# define K_MAJ 4 ++# define K_MIN1 13 ++# define K_MIN2 0 ++# if LINUX_VERSION_CODE < KERNEL_VERSION(K_MAJ, K_MIN1, K_MIN2) ++ ++# ifndef PEDANTIC ++# warning "KTLS requires Kernel Headers >= 4.13.0" ++# warning "Skipping Compilation of KTLS" ++# endif ++ ++# define TLS_TX 1 ++# define TLS_RX 2 ++ ++# define TLS_CIPHER_AES_GCM_128 51 ++# define TLS_CIPHER_AES_GCM_128_IV_SIZE 8 ++# define TLS_CIPHER_AES_GCM_128_KEY_SIZE 16 ++# define TLS_CIPHER_AES_GCM_128_SALT_SIZE 4 ++# define TLS_CIPHER_AES_GCM_128_TAG_SIZE 16 ++# define TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE 8 ++ ++# define TLS_SET_RECORD_TYPE 1 ++ ++struct tls_crypto_info { ++ unsigned short version; ++ unsigned short cipher_type; ++}; ++ ++struct tls12_crypto_info_aes_gcm_128 { ++ struct tls_crypto_info info; ++ unsigned char iv[TLS_CIPHER_AES_GCM_128_IV_SIZE]; ++ unsigned char key[TLS_CIPHER_AES_GCM_128_KEY_SIZE]; ++ unsigned char salt[TLS_CIPHER_AES_GCM_128_SALT_SIZE]; ++ unsigned char rec_seq[TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE]; ++}; ++ ++/* Dummy functions here */ ++static ossl_inline int ktls_enable(int fd) ++{ ++ return 0; ++} ++ ++static ossl_inline int ktls_start(int fd, ++ struct tls12_crypto_info_aes_gcm_128 ++ *crypto_info, size_t len, int is_tx) ++{ ++ return 0; ++} ++ ++static ossl_inline int ktls_send_ctrl_message(int fd, unsigned char record_type, ++ const void *data, size_t length) ++{ ++ return -1; ++} ++ ++static ossl_inline int ktls_read_record(int fd, void *data, size_t length) ++{ ++ return -1; ++} ++ ++static ossl_inline ossl_ssize_t ktls_sendfile(int s, int fd, off_t off, size_t size, int flags) ++{ ++ return -1; ++} ++ ++# else /* KERNEL_VERSION */ ++ ++# include ++# include ++# include ++# include ++# include "openssl/ssl3.h" ++# include "openssl/tls1.h" ++# include "openssl/evp.h" ++ ++# ifndef SOL_TLS ++# define SOL_TLS 282 ++# endif ++ ++# ifndef TCP_ULP ++# define TCP_ULP 31 ++# endif ++ ++# ifndef TLS_RX ++# define TLS_RX 2 ++# endif ++ ++/* ++ * When successful, this socket option doesn't change the behaviour of the ++ * TCP socket, except changing the TCP setsockopt handler to enable the ++ * processing of SOL_TLS socket options. All other functionality remains the ++ * same. ++ */ ++static ossl_inline int ktls_enable(int fd) ++{ ++ return setsockopt(fd, SOL_TCP, TCP_ULP, "tls", sizeof("tls")) ? 0 : 1; ++} ++ ++/* ++ * The TLS_TX socket option changes the send/sendmsg handlers of the TCP socket. ++ * If successful, then data sent using this socket will be encrypted and ++ * encapsulated in TLS records using the crypto_info provided here. ++ * The TLS_RX socket option changes the recv/recvmsg handlers of the TCP socket. ++ * If successful, then data received using this socket will be decrypted, ++ * authenticated and decapsulated using the crypto_info provided here. ++ */ ++static ossl_inline int ktls_start(int fd, ++ struct tls12_crypto_info_aes_gcm_128 ++ *crypto_info, size_t len, int is_tx) ++{ ++ return setsockopt(fd, SOL_TLS, is_tx ? TLS_TX : TLS_RX, ++ crypto_info, sizeof(*crypto_info)) ? 0 : 1; ++} ++ ++/* ++ * Send a TLS record using the crypto_info 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; ++ int cmsg_len = sizeof(record_type); ++ struct cmsghdr *cmsg; ++ union { ++ struct cmsghdr hdr; ++ char buf[CMSG_SPACE(sizeof(unsigned char))]; ++ } cmsgbuf; ++ struct iovec msg_iov; /* Vector of data to send/receive into */ ++ ++ memset(&msg, 0, sizeof(msg)); ++ msg.msg_control = cmsgbuf.buf; ++ msg.msg_controllen = sizeof(cmsgbuf.buf); ++ cmsg = CMSG_FIRSTHDR(&msg); ++ cmsg->cmsg_level = SOL_TLS; ++ 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); ++} ++ ++/* ++ * KTLS enables the sendfile system call to send data from a file over TLS. ++ * @flags are ignored on Linux. (placeholder for FreeBSD sendfile) ++ * */ ++static ossl_inline ossl_ssize_t ktls_sendfile(int s, int fd, off_t off, size_t size, int flags) ++{ ++ return sendfile(s, fd, &off, size); ++} ++ ++# define K_MIN1_RX 17 ++# if LINUX_VERSION_CODE < KERNEL_VERSION(K_MAJ, K_MIN1_RX, K_MIN2) ++ ++# ifndef PEDANTIC ++# warning "KTLS requires Kernel Headers >= 4.17.0 for receiving" ++# warning "Skipping Compilation of KTLS receive data path" ++# endif ++ ++static ossl_inline int ktls_read_record(int fd, void *data, size_t length) ++{ ++ return -1; ++} ++ ++# else ++ ++/* ++ * Receive a TLS record using the crypto_info provided in ktls_start. ++ * The kernel strips the TLS record header, IV and authentication tag, ++ * returning only the plaintext data or an error on failure. ++ * We add the TLS record header here to satisfy routines in rec_layer_s3.c ++ */ ++static ossl_inline int ktls_read_record(int fd, void *data, size_t length) ++{ ++ struct msghdr msg; ++ struct cmsghdr *cmsg; ++ union { ++ struct cmsghdr hdr; ++ char buf[CMSG_SPACE(sizeof(unsigned char))]; ++ } cmsgbuf; ++ struct iovec msg_iov; ++ int ret; ++ unsigned char *p = data; ++ const size_t prepend_length = SSL3_RT_HEADER_LENGTH; ++ ++ if (length < prepend_length + EVP_GCM_TLS_TAG_LEN) { ++ errno = EINVAL; ++ return -1; ++ } *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***