git: afdbccbf4017 - releng/13.0 - OpenSSL: Support for kernel TLS offload (KTLS)
John Baldwin
jhb at FreeBSD.org
Sat Feb 6 01:58:49 UTC 2021
The branch releng/13.0 has been updated by jhb:
URL: https://cgit.FreeBSD.org/src/commit/?id=afdbccbf4017c17eed95640bd9daad743388a22b
commit afdbccbf4017c17eed95640bd9daad743388a22b
Author: John Baldwin <jhb at FreeBSD.org>
AuthorDate: 2021-01-16 00:17:31 +0000
Commit: John Baldwin <jhb at FreeBSD.org>
CommitDate: 2021-02-06 01:57:55 +0000
OpenSSL: Support for kernel TLS offload (KTLS)
This merges upstream patches from OpenSSL's master branch to add
KTLS infrastructure for TLS 1.0-1.3 including both RX and TX
offload and SSL_sendfile support on both Linux and FreeBSD.
Note that TLS 1.3 only supports TX offload.
A new WITH/WITHOUT_OPENSSL_KTLS determines if OpenSSL is built with
KTLS support. It defaults to enabled on amd64 and disabled on all
other architectures.
Approved by: re (gjb)
Sponsored by: Netflix
(cherry picked from commit aa906e2a4957db700d9e6cc60857e1afe1aecc85)
(cherry picked from commit c1c52cd57e8810ca294d02220dfa72607c9a5567)
---
crypto/openssl/CHANGES | 5 +
crypto/openssl/Configure | 29 ++
crypto/openssl/INSTALL | 9 +
crypto/openssl/apps/s_client.c | 6 +
crypto/openssl/apps/s_server.c | 6 +
crypto/openssl/crypto/bio/b_sock2.c | 12 +
crypto/openssl/crypto/bio/bss_conn.c | 46 ++-
crypto/openssl/crypto/bio/bss_sock.c | 57 ++-
crypto/openssl/crypto/err/openssl.txt | 1 +
crypto/openssl/crypto/evp/e_aes.c | 8 +
crypto/openssl/doc/man3/BIO_ctrl.pod | 21 +-
crypto/openssl/doc/man3/SSL_CTX_set_mode.pod | 17 +
.../man3/SSL_CTX_set_record_padding_callback.pod | 10 +-
crypto/openssl/doc/man3/SSL_write.pod | 31 +-
crypto/openssl/engines/e_afalg.c | 3 +-
crypto/openssl/include/internal/bio.h | 39 ++
crypto/openssl/include/internal/ktls.h | 403 +++++++++++++++++++++
crypto/openssl/include/openssl/bio.h | 20 +
crypto/openssl/include/openssl/err.h | 1 +
crypto/openssl/include/openssl/evp.h | 2 +
crypto/openssl/include/openssl/ssl.h | 12 +-
crypto/openssl/include/openssl/sslerr.h | 1 +
crypto/openssl/ssl/build.info | 5 +
crypto/openssl/ssl/ktls.c | 221 +++++++++++
crypto/openssl/ssl/record/rec_layer_s3.c | 137 +++++--
crypto/openssl/ssl/record/record.h | 2 +
crypto/openssl/ssl/record/record_local.h | 3 +
crypto/openssl/ssl/record/ssl3_buffer.c | 33 +-
crypto/openssl/ssl/record/ssl3_record.c | 47 ++-
crypto/openssl/ssl/ssl_err.c | 1 +
crypto/openssl/ssl/ssl_lib.c | 104 +++++-
crypto/openssl/ssl/ssl_local.h | 13 +
crypto/openssl/ssl/t1_enc.c | 128 +++++++
crypto/openssl/ssl/tls13_enc.c | 81 ++++-
secure/lib/libcrypto/Makefile | 18 +-
secure/lib/libcrypto/opensslconf.h.in | 3 +
secure/lib/libssl/Makefile | 6 +
secure/lib/libssl/Version.map | 6 +
share/mk/src.opts.mk | 7 +
tools/build/options/WITHOUT_OPENSSL_KTLS | 1 +
tools/build/options/WITH_OPENSSL_KTLS | 1 +
41 files changed, 1465 insertions(+), 91 deletions(-)
diff --git a/crypto/openssl/CHANGES b/crypto/openssl/CHANGES
index 37dd60b726ee..4d61c1dadbaa 100644
--- a/crypto/openssl/CHANGES
+++ b/crypto/openssl/CHANGES
@@ -390,6 +390,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 a/crypto/openssl/Configure b/crypto/openssl/Configure
index 1d73d06e1b3b..1423e1bfe14f 100755
--- a/crypto/openssl/Configure
+++ b/crypto/openssl/Configure
@@ -387,6 +387,7 @@ my @disablables = (
"heartbeats",
"hw(-.+)?",
"idea",
+ "ktls",
"makedepend",
"md2",
"md4",
@@ -474,6 +475,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
@@ -1580,6 +1582,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 <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-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 a/crypto/openssl/INSTALL b/crypto/openssl/INSTALL
index f5118428b3bc..be84f2aa8e5d 100644
--- a/crypto/openssl/INSTALL
+++ b/crypto/openssl/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 a/crypto/openssl/apps/s_client.c b/crypto/openssl/apps/s_client.c
index 83b3fc9c7f13..68bd9ced015f 100644
--- a/crypto/openssl/apps/s_client.c
+++ b/crypto/openssl/apps/s_client.c
@@ -3282,6 +3282,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 a/crypto/openssl/apps/s_server.c b/crypto/openssl/apps/s_server.c
index 0ba75999fd28..ddc0b4bcd76d 100644
--- a/crypto/openssl/apps/s_server.c
+++ b/crypto/openssl/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 a/crypto/openssl/crypto/bio/b_sock2.c b/crypto/openssl/crypto/bio/b_sock2.c
index 335dfabc6180..80ef348d9254 100644
--- a/crypto/openssl/crypto/bio/b_sock2.c
+++ b/crypto/openssl/crypto/bio/b_sock2.c
@@ -12,6 +12,7 @@
#include <errno.h>
#include "bio_local.h"
+#include "internal/ktls.h"
#include <openssl/err.h>
@@ -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 a/crypto/openssl/crypto/bio/bss_conn.c b/crypto/openssl/crypto/bio/bss_conn.c
index 807a82b23ba2..d4786442803e 100644
--- a/crypto/openssl/crypto/bio/bss_conn.c
+++ b/crypto/openssl/crypto/bio/bss_conn.c
@@ -11,6 +11,7 @@
#include <errno.h>
#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;
@@ -320,7 +324,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))
@@ -345,7 +354,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))
@@ -361,6 +379,9 @@ 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
+ ktls_crypto_info_t *crypto_info;
+# endif
data = (BIO_CONNECT *)b->ptr;
@@ -520,6 +541,27 @@ 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:
+ crypto_info = (ktls_crypto_info_t *)ptr;
+ ret = ktls_start(b->num, 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 a/crypto/openssl/crypto/bio/bss_sock.c b/crypto/openssl/crypto/bio/bss_sock.c
index 6251f3d46a17..a1fc23c7c938 100644
--- a/crypto/openssl/crypto/bio/bss_sock.c
+++ b/crypto/openssl/crypto/bio/bss_sock.c
@@ -11,6 +11,7 @@
#include <errno.h>
#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,9 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr)
{
long ret = 1;
int *ip;
+# ifndef OPENSSL_NO_KTLS
+ ktls_crypto_info_t *crypto_info;
+# endif
switch (cmd) {
case BIO_C_SET_FD:
@@ -153,6 +183,27 @@ 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:
+ crypto_info = (ktls_crypto_info_t *)ptr;
+ ret = ktls_start(b->num, 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 a/crypto/openssl/crypto/err/openssl.txt b/crypto/openssl/crypto/err/openssl.txt
index 815460b24f67..d547c45913d6 100644
--- a/crypto/openssl/crypto/err/openssl.txt
+++ b/crypto/openssl/crypto/err/openssl.txt
@@ -1318,6 +1318,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 a/crypto/openssl/crypto/evp/e_aes.c b/crypto/openssl/crypto/evp/e_aes.c
index 405ddbf9bf09..4640c7528a20 100644
--- a/crypto/openssl/crypto/evp/e_aes.c
+++ b/crypto/openssl/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 a/crypto/openssl/doc/man3/BIO_ctrl.pod b/crypto/openssl/doc/man3/BIO_ctrl.pod
index 2e438c3ce952..31b18b2879fe 100644
--- a/crypto/openssl/doc/man3/BIO_ctrl.pod
+++ b/crypto/openssl/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-2020 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/crypto/openssl/doc/man3/SSL_CTX_set_mode.pod b/crypto/openssl/doc/man3/SSL_CTX_set_mode.pod
index 85e3353e0e2c..27eaebad1ea0 100644
--- a/crypto/openssl/doc/man3/SSL_CTX_set_mode.pod
+++ b/crypto/openssl/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<SSL_write(3)>, L<SSL_get_error(3)>
=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 a/crypto/openssl/doc/man3/SSL_CTX_set_record_padding_callback.pod b/crypto/openssl/doc/man3/SSL_CTX_set_record_padding_callback.pod
index 13e56f0c57f6..247a39fc0355 100644
--- a/crypto/openssl/doc/man3/SSL_CTX_set_record_padding_callback.pod
+++ b/crypto/openssl/doc/man3/SSL_CTX_set_record_padding_callback.pod
@@ -16,7 +16,7 @@ SSL_set_block_padding - install callback to specify TLS 1.3 record padding
#include <openssl/ssl.h>
void SSL_CTX_set_record_padding_callback(SSL_CTX *ctx, size_t (*cb)(SSL *s, int type, size_t len, void *arg));
- void SSL_set_record_padding_callback(SSL *ssl, size_t (*cb)(SSL *s, int type, size_t len, void *arg));
+ int SSL_set_record_padding_callback(SSL *ssl, size_t (*cb)(SSL *s, int type, size_t len, void *arg));
void SSL_CTX_set_record_padding_callback_arg(SSL_CTX *ctx, void *arg);
void *SSL_CTX_get_record_padding_callback_arg(const SSL_CTX *ctx);
@@ -32,6 +32,8 @@ SSL_set_block_padding - install callback to specify TLS 1.3 record padding
SSL_CTX_set_record_padding_callback() or SSL_set_record_padding_callback()
can be used to assign a callback function I<cb> to specify the padding
for TLS 1.3 records. The value set in B<ctx> is copied to a new SSL by SSL_new().
+Kernel TLS is not possible if the record padding callback is set, and the callback
+function cannot be set if Kernel TLS is already configured for the current SSL object.
SSL_CTX_set_record_padding_callback_arg() and SSL_set_record_padding_callback_arg()
assign a value B<arg> that is passed to the callback when it is invoked. The value
@@ -64,6 +66,9 @@ indicates no padding will be added. A return value that causes the record to
exceed the maximum record size (SSL3_RT_MAX_PLAIN_LENGTH) will pad out to the
maximum record size.
+The SSL_CTX_get_record_padding_callback_arg() function returns 1 on success or 0 if
+the callback function is not set because Kernel TLS is configured for the SSL object.
+
=head1 NOTES
The default behavior is to add no padding to the record.
@@ -84,6 +89,9 @@ L<ssl(7)>, L<SSL_new(3)>
The record padding API was added for TLS 1.3 support in OpenSSL 1.1.1.
+The return type of SSL_CTX_set_record_padding_callback() function was
+changed to int in OpenSSL 3.0.
+
=head1 COPYRIGHT
Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/crypto/openssl/doc/man3/SSL_write.pod b/crypto/openssl/doc/man3/SSL_write.pod
index 5e3ce1e7e4dd..20c7953deb06 100644
--- a/crypto/openssl/doc/man3/SSL_write.pod
+++ b/crypto/openssl/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 <openssl/ssl.h>
+ 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<num> bytes from the buffer B<buf> into
the specified B<ssl> connection. On success SSL_write_ex() will store the number
of bytes written in B<*written>.
+SSL_sendfile() writes B<size> bytes from offset B<offset> in the file
+descriptor B<fd> to the specified SSL connection B<s>. 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<flags> 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<lt> 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<SSL_get_error(3)>, L<SSL_read_ex(3)>, L<SSL_read(3)>
L<SSL_CTX_set_mode(3)>, L<SSL_CTX_new(3)>,
L<SSL_connect(3)>, L<SSL_accept(3)>
-L<SSL_set_connect_state(3)>,
+L<SSL_set_connect_state(3)>, L<BIO_ctrl(3)>,
L<ssl(7)>, L<bio(7)>
=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 a/crypto/openssl/engines/e_afalg.c b/crypto/openssl/engines/e_afalg.c
index 4b1722846133..5ef3a8d457e6 100644
--- a/crypto/openssl/engines/e_afalg.c
+++ b/crypto/openssl/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 a/crypto/openssl/include/internal/bio.h b/crypto/openssl/include/internal/bio.h
index c343b276295c..521b5fa2198f 100644
--- a/crypto/openssl/include/internal/bio.h
+++ b/crypto/openssl/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 <openssl/bio.h>
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 a/crypto/openssl/include/internal/ktls.h b/crypto/openssl/include/internal/ktls.h
new file mode 100644
index 000000000000..9032c0ed6174
--- /dev/null
+++ b/crypto/openssl/include/internal/ktls.h
@@ -0,0 +1,403 @@
+/*
+ * 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
+ */
+
+#if defined(OPENSSL_SYS_LINUX)
+# ifndef OPENSSL_NO_KTLS
+# include <linux/version.h>
+# if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
+# define OPENSSL_NO_KTLS
+# ifndef PEDANTIC
+# warning "KTLS requires Kernel Headers >= 4.13.0"
+# warning "Skipping Compilation of KTLS"
+# endif
+# endif
+# endif
+#endif
+
+#ifndef HEADER_INTERNAL_KTLS
+# define HEADER_INTERNAL_KTLS
+# ifndef OPENSSL_NO_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 "openssl/ssl3.h"
+
+# ifndef TCP_RXTLS_ENABLE
+# define OPENSSL_NO_KTLS_RX
+# endif
+# define OPENSSL_KTLS_AES_GCM_128
+# define OPENSSL_KTLS_AES_GCM_256
+# define OPENSSL_KTLS_TLS13
+
+/*
+ * Only used by the tests in sslapitest.c.
+ */
+# define TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE 8
+# define TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE 8
+
+typedef struct tls_enable ktls_crypto_info_t;
+
+/*
+ * 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.
+ *
+ * The TCP_RXTLS_ENABLE socket option marks the incoming socket buffer
+ * as using TLS. If successful, then data received for this socket will
+ * be authenticated and decrypted using the tls_en provided here.
+ */
+static ossl_inline int ktls_start(int fd, ktls_crypto_info_t *tls_en, int is_tx)
+{
+ if (is_tx)
+ return setsockopt(fd, IPPROTO_TCP, TCP_TXTLS_ENABLE,
+ tls_en, sizeof(*tls_en)) ? 0 : 1;
+# ifndef OPENSSL_NO_KTLS_RX
+ return setsockopt(fd, IPPROTO_TCP, TCP_RXTLS_ENABLE, tls_en,
+ sizeof(*tls_en)) ? 0 : 1;
+# else
+ return 0;
+# endif
+}
+
+/*
+ * 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);
+}
+
+# ifdef OPENSSL_NO_KTLS_RX
+
+static ossl_inline int ktls_read_record(int fd, void *data, size_t length)
+{
+ return -1;
+}
+
+# else /* !defined(OPENSSL_NO_KTLS_RX) */
+
+/*
+ * Receive a TLS record using the tls_en provided in ktls_start. The
+ * kernel strips any explicit IV and authentication tag, but provides
+ * the TLS record header via a control message. If there is an error
+ * with the TLS record such as an invalid header, invalid padding, or
+ * authentication failure recvmsg() will fail with an error.
+ */
+static ossl_inline int ktls_read_record(int fd, void *data, size_t length)
+{
+ struct msghdr msg = { 0 };
+ int cmsg_len = sizeof(struct tls_get_record);
+ struct tls_get_record *tgr;
+ struct cmsghdr *cmsg;
+ char buf[CMSG_SPACE(cmsg_len)];
+ struct iovec msg_iov; /* Vector of data to send/receive into */
+ int ret;
+ unsigned char *p = data;
+ const size_t prepend_length = SSL3_RT_HEADER_LENGTH;
+
+ if (length <= prepend_length) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ msg.msg_control = buf;
+ msg.msg_controllen = sizeof(buf);
+
+ msg_iov.iov_base = p + prepend_length;
+ msg_iov.iov_len = length - prepend_length;
+ msg.msg_iov = &msg_iov;
+ msg.msg_iovlen = 1;
+
+ ret = recvmsg(fd, &msg, 0);
+ if (ret <= 0)
+ return ret;
+
+ if ((msg.msg_flags & (MSG_EOR | MSG_CTRUNC)) != MSG_EOR) {
+ errno = EMSGSIZE;
+ return -1;
+ }
+
+ if (msg.msg_controllen == 0) {
+ errno = EBADMSG;
+ return -1;
+ }
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ if (cmsg->cmsg_level != IPPROTO_TCP || cmsg->cmsg_type != TLS_GET_RECORD
+ || cmsg->cmsg_len != CMSG_LEN(cmsg_len)) {
+ errno = EBADMSG;
+ return -1;
+ }
+
+ tgr = (struct tls_get_record *)CMSG_DATA(cmsg);
+ p[0] = tgr->tls_type;
+ p[1] = tgr->tls_vmajor;
+ p[2] = tgr->tls_vminor;
+ *(uint16_t *)(p + 3) = htons(ret);
+
+ return ret + prepend_length;
+}
+
+# endif /* OPENSSL_NO_KTLS_RX */
+
+/*
+ * 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/tls.h>
+# if LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)
+# define OPENSSL_NO_KTLS_RX
+# ifndef PEDANTIC
+# warning "KTLS requires Kernel Headers >= 4.17.0 for receiving"
+# warning "Skipping Compilation of KTLS receive data path"
+# endif
+# endif
+# define OPENSSL_KTLS_AES_GCM_128
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0)
+# define OPENSSL_KTLS_AES_GCM_256
+# define OPENSSL_KTLS_TLS13
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)
+# define OPENSSL_KTLS_AES_CCM_128
+# endif
+# endif
+
+# include <sys/sendfile.h>
+# include <netinet/tcp.h>
+# include <linux/socket.h>
+# 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
*** 1679 LINES SKIPPED ***
More information about the dev-commits-src-all
mailing list