ssl: Linux TLS Tx Offload
This patch adds support for the Linux TLS Tx socket option. If the socket option is successful, then the data-path of the TCP socket is implemented by the kernel. We choose to set this option at the earliest - just after CCS is complete. Signed-off-by: Boris Pismenny <borisp@mellanox.com> Reviewed-by: Tim Hudson <tjh@openssl.org> Reviewed-by: Paul Yang <yang.yang@baishancloud.com> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5253)
This commit is contained in:
parent
ecd1557fb4
commit
50ec750567
10 changed files with 235 additions and 50 deletions
|
@ -5,7 +5,7 @@
|
|||
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 control operations
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
@ -34,6 +34,8 @@ 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);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
BIO_ctrl(), BIO_callback_ctrl(), BIO_ptr_ctrl() and BIO_int_ctrl()
|
||||
|
@ -72,6 +74,9 @@ 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() return 1 if the BIO is using the Kernel TLS data-path for
|
||||
sending. Otherwise, it returns zero.
|
||||
|
||||
=head1 RETURN VALUES
|
||||
|
||||
BIO_reset() normally returns 1 for success and 0 or -1 for failure. File
|
||||
|
@ -92,6 +97,9 @@ 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() return 1 if the BIO is using the Kernel TLS data-path for
|
||||
sending. Otherwise, it returns zero.
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
BIO_flush(), because it can write data may return 0 or -1 indicating
|
||||
|
@ -124,6 +132,10 @@ 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() function was added in OpenSSL 3.0.0.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
|
|
|
@ -105,6 +105,22 @@ Enable asynchronous processing. TLS I/O operations may indicate a retry with
|
|||
SSL_ERROR_WANT_ASYNC with this mode set if an asynchronous capable engine is
|
||||
used to perform cryptographic operations. See L<SSL_get_error(3)>.
|
||||
|
||||
=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
|
||||
|
@ -125,6 +141,7 @@ L<SSL_write(3)>, L<SSL_get_error(3)>
|
|||
=head1 HISTORY
|
||||
|
||||
SSL_MODE_ASYNC was first added to OpenSSL 1.1.0.
|
||||
SSL_MODE_NO_KTLS_TX was first added to OpenSSL 3.0.0.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
|
|
|
@ -493,6 +493,10 @@ typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx);
|
|||
* Support Asynchronous operation
|
||||
*/
|
||||
# define SSL_MODE_ASYNC 0x00000100U
|
||||
/*
|
||||
* Use the kernel TLS transmission data-path.
|
||||
*/
|
||||
# define SSL_MODE_NO_KTLS_TX 0x00000200U
|
||||
|
||||
/* Cert related flags */
|
||||
/*
|
||||
|
|
|
@ -743,6 +743,18 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
|
|||
s->s3->empty_fragment_done = 1;
|
||||
}
|
||||
|
||||
if (BIO_get_ktls_send(s->wbio)) {
|
||||
/*
|
||||
* ktls doesn't modify the buffer, but to avoid a warning we need to
|
||||
* discard the const qualifier.
|
||||
* This doesn't leak memory because the buffers have been released when
|
||||
* switching to ktls.
|
||||
*/
|
||||
SSL3_BUFFER_set_buf(&s->rlayer.wbuf[0], (unsigned char *)buf);
|
||||
SSL3_BUFFER_set_offset(&s->rlayer.wbuf[0], 0);
|
||||
goto wpacket_init_complete;
|
||||
}
|
||||
|
||||
if (create_empty_fragment) {
|
||||
wb = &s->rlayer.wbuf[0];
|
||||
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
|
||||
|
@ -812,6 +824,8 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
|
|||
}
|
||||
}
|
||||
|
||||
wpacket_init_complete:
|
||||
|
||||
totlen = 0;
|
||||
/* Clear our SSL3_RECORD structures */
|
||||
memset(wr, 0, sizeof(wr));
|
||||
|
@ -853,15 +867,19 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
|
|||
if (s->compress != NULL)
|
||||
maxcomplen += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
|
||||
|
||||
/* write the header */
|
||||
if (!WPACKET_put_bytes_u8(thispkt, rectype)
|
||||
/*
|
||||
* When using offload kernel will write the header.
|
||||
* Otherwise write the header now
|
||||
*/
|
||||
if (!BIO_get_ktls_send(s->wbio)
|
||||
&& (!WPACKET_put_bytes_u8(thispkt, rectype)
|
||||
|| !WPACKET_put_bytes_u16(thispkt, version)
|
||||
|| !WPACKET_start_sub_packet_u16(thispkt)
|
||||
|| (eivlen > 0
|
||||
&& !WPACKET_allocate_bytes(thispkt, eivlen, NULL))
|
||||
|| (maxcomplen > 0
|
||||
&& !WPACKET_reserve_bytes(thispkt, maxcomplen,
|
||||
&compressdata))) {
|
||||
&compressdata)))) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
|
@ -887,12 +905,16 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
|
|||
goto err;
|
||||
}
|
||||
} else {
|
||||
if (!WPACKET_memcpy(thispkt, thiswr->input, thiswr->length)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
if (BIO_get_ktls_send(s->wbio)) {
|
||||
SSL3_RECORD_reset_data(&wr[j]);
|
||||
} else {
|
||||
if (!WPACKET_memcpy(thispkt, thiswr->input, thiswr->length)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
SSL3_RECORD_reset_input(&wr[j]);
|
||||
}
|
||||
SSL3_RECORD_reset_input(&wr[j]);
|
||||
}
|
||||
|
||||
if (SSL_TREAT_AS_TLS13(s)
|
||||
|
@ -967,24 +989,26 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
|
|||
* This will be at most one cipher block or the tag length if using
|
||||
* AEAD. SSL_RT_MAX_CIPHER_BLOCK_SIZE covers either case.
|
||||
*/
|
||||
if (!WPACKET_reserve_bytes(thispkt, SSL_RT_MAX_CIPHER_BLOCK_SIZE,
|
||||
NULL)
|
||||
/*
|
||||
* We also need next the amount of bytes written to this
|
||||
* sub-packet
|
||||
*/
|
||||
if (!BIO_get_ktls_send(s->wbio)) {
|
||||
if (!WPACKET_reserve_bytes(thispkt,
|
||||
SSL_RT_MAX_CIPHER_BLOCK_SIZE,
|
||||
NULL)
|
||||
/*
|
||||
* We also need next the amount of bytes written to this
|
||||
* sub-packet
|
||||
*/
|
||||
|| !WPACKET_get_length(thispkt, &len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Get a pointer to the start of this record excluding header */
|
||||
recordstart = WPACKET_get_curr(thispkt) - len;
|
||||
SSL3_RECORD_set_data(thiswr, recordstart);
|
||||
SSL3_RECORD_reset_input(thiswr);
|
||||
SSL3_RECORD_set_length(thiswr, len);
|
||||
}
|
||||
|
||||
/* Get a pointer to the start of this record excluding header */
|
||||
recordstart = WPACKET_get_curr(thispkt) - len;
|
||||
|
||||
SSL3_RECORD_set_data(thiswr, recordstart);
|
||||
SSL3_RECORD_reset_input(thiswr);
|
||||
SSL3_RECORD_set_length(thiswr, len);
|
||||
}
|
||||
|
||||
if (s->statem.enc_write_state == ENC_WRITE_STATE_WRITE_PLAIN_ALERTS) {
|
||||
|
@ -1000,12 +1024,14 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
|
|||
goto err;
|
||||
}
|
||||
} else {
|
||||
if (s->method->ssl3_enc->enc(s, wr, numpipes, 1) < 1) {
|
||||
if (!ossl_statem_in_error(s)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
if (!BIO_get_ktls_send(s->wbio)) {
|
||||
if (s->method->ssl3_enc->enc(s, wr, numpipes, 1) < 1) {
|
||||
if (!ossl_statem_in_error(s)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1015,13 +1041,17 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
|
|||
thispkt = &pkt[j];
|
||||
thiswr = &wr[j];
|
||||
|
||||
if (BIO_get_ktls_send(s->wbio))
|
||||
goto mac_done;
|
||||
|
||||
/* Allocate bytes for the encryption overhead */
|
||||
if (!WPACKET_get_length(thispkt, &origlen)
|
||||
/* Encryption should never shrink the data! */
|
||||
|| origlen > thiswr->length
|
||||
|| (thiswr->length > origlen
|
||||
&& !WPACKET_allocate_bytes(thispkt,
|
||||
thiswr->length - origlen, NULL))) {
|
||||
thiswr->length - origlen,
|
||||
NULL))) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DO_SSL3_WRITE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
|
@ -1066,13 +1096,8 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
|
|||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* we should now have thiswr->data pointing to the encrypted data, which
|
||||
* is thiswr->length long
|
||||
*/
|
||||
SSL3_RECORD_set_type(thiswr, type); /* not needed but helps for
|
||||
* debugging */
|
||||
SSL3_RECORD_add_length(thiswr, SSL3_RT_HEADER_LENGTH);
|
||||
/* header is added by the kernel when using offload */
|
||||
SSL3_RECORD_add_length(&wr[j], SSL3_RT_HEADER_LENGTH);
|
||||
|
||||
if (create_empty_fragment) {
|
||||
/*
|
||||
|
@ -1089,6 +1114,14 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
|
|||
return 1;
|
||||
}
|
||||
|
||||
mac_done:
|
||||
/*
|
||||
* we should now have thiswr->data pointing to the encrypted data, which
|
||||
* is thiswr->length long
|
||||
*/
|
||||
SSL3_RECORD_set_type(thiswr, type); /* not needed but helps for
|
||||
* debugging */
|
||||
|
||||
/* now let's set up wb */
|
||||
SSL3_BUFFER_set_left(&s->rlayer.wbuf[j],
|
||||
prefix_len + SSL3_RECORD_get_length(thiswr));
|
||||
|
@ -1142,6 +1175,21 @@ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, size_t len,
|
|||
clear_sys_error();
|
||||
if (s->wbio != NULL) {
|
||||
s->rwstate = SSL_WRITING;
|
||||
|
||||
/*
|
||||
* To prevent coalescing of control and data messages,
|
||||
* such as in buffer_write, we flush the BIO
|
||||
*/
|
||||
if (BIO_get_ktls_send(s->wbio) && type != SSL3_RT_APPLICATION_DATA) {
|
||||
i = BIO_flush(s->wbio);
|
||||
if (i <= 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
if (BIO_get_ktls_send(s->wbio)
|
||||
&& type != SSL3_RT_APPLICATION_DATA) {
|
||||
BIO_set_ktls_ctrl_msg(s->wbio, type);
|
||||
}
|
||||
/* TODO(size_t): Convert this call */
|
||||
i = BIO_write(s->wbio, (char *)
|
||||
&(SSL3_BUFFER_get_buf(&wb[currbuf])
|
||||
|
|
|
@ -88,6 +88,7 @@ int ssl3_release_write_buffer(SSL *s);
|
|||
#define SSL3_RECORD_get_input(r) ((r)->input)
|
||||
#define SSL3_RECORD_set_input(r, i) ((r)->input = (i))
|
||||
#define SSL3_RECORD_reset_input(r) ((r)->input = (r)->data)
|
||||
#define SSL3_RECORD_reset_data(r) ((r)->data = (r)->input)
|
||||
#define SSL3_RECORD_get_seq_num(r) ((r)->seq_num)
|
||||
#define SSL3_RECORD_get_off(r) ((r)->off)
|
||||
#define SSL3_RECORD_set_off(r, o) ((r)->off = (o))
|
||||
|
|
|
@ -111,23 +111,27 @@ int ssl3_setup_write_buffer(SSL *s, size_t numwpipes, size_t len)
|
|||
for (currpipe = 0; currpipe < numwpipes; currpipe++) {
|
||||
SSL3_BUFFER *thiswb = &wb[currpipe];
|
||||
|
||||
if (thiswb->buf != NULL && thiswb->len != len) {
|
||||
if (thiswb->len != len) {
|
||||
OPENSSL_free(thiswb->buf);
|
||||
thiswb->buf = NULL; /* force reallocation */
|
||||
}
|
||||
|
||||
if (thiswb->buf == NULL) {
|
||||
p = OPENSSL_malloc(len);
|
||||
if (p == NULL) {
|
||||
s->rlayer.numwpipes = currpipe;
|
||||
/*
|
||||
* We've got a malloc failure, and we're still initialising
|
||||
* buffers. We assume we're so doomed that we won't even be able
|
||||
* to send an alert.
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_NO_ALERT,
|
||||
SSL_F_SSL3_SETUP_WRITE_BUFFER, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
if (s->wbio == NULL || !BIO_get_ktls_send(s->wbio)) {
|
||||
p = OPENSSL_malloc(len);
|
||||
if (p == NULL) {
|
||||
s->rlayer.numwpipes = currpipe;
|
||||
/*
|
||||
* We've got a malloc failure, and we're still initialising
|
||||
* buffers. We assume we're so doomed that we won't even be able
|
||||
* to send an alert.
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_NO_ALERT,
|
||||
SSL_F_SSL3_SETUP_WRITE_BUFFER, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
p = NULL;
|
||||
}
|
||||
memset(thiswb, 0, sizeof(SSL3_BUFFER));
|
||||
thiswb->buf = p;
|
||||
|
@ -160,7 +164,8 @@ int ssl3_release_write_buffer(SSL *s)
|
|||
while (pipes > 0) {
|
||||
wb = &RECORD_LAYER_get_wbuf(&s->rlayer)[pipes - 1];
|
||||
|
||||
OPENSSL_free(wb->buf);
|
||||
if (s->wbio == NULL || !BIO_get_ktls_send(s->wbio))
|
||||
OPENSSL_free(wb->buf);
|
||||
wb->buf = NULL;
|
||||
pipes--;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <openssl/ct.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/refcount.h"
|
||||
#include "internal/ktls.h"
|
||||
|
||||
static int ssl_undefined_function_1(SSL *ssl, SSL3_RECORD *r, size_t s, int t)
|
||||
{
|
||||
|
@ -1146,11 +1147,15 @@ void SSL_free(SSL *s)
|
|||
dane_final(&s->dane);
|
||||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data);
|
||||
|
||||
RECORD_LAYER_release(&s->rlayer);
|
||||
|
||||
/* Ignore return value */
|
||||
ssl_free_wbio_buffer(s);
|
||||
|
||||
BIO_free_all(s->wbio);
|
||||
s->wbio = NULL;
|
||||
BIO_free_all(s->rbio);
|
||||
s->rbio = NULL;
|
||||
|
||||
BUF_MEM_free(s->init_buf);
|
||||
|
||||
|
@ -1201,8 +1206,6 @@ void SSL_free(SSL *s)
|
|||
if (s->method != NULL)
|
||||
s->method->ssl_free(s);
|
||||
|
||||
RECORD_LAYER_release(&s->rlayer);
|
||||
|
||||
SSL_CTX_free(s->ctx);
|
||||
|
||||
ASYNC_WAIT_CTX_free(s->waitctx);
|
||||
|
@ -1342,6 +1345,15 @@ int SSL_set_fd(SSL *s, int fd)
|
|||
}
|
||||
BIO_set_fd(bio, fd, BIO_NOCLOSE);
|
||||
SSL_set_bio(s, bio, bio);
|
||||
#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 /* OPENSSL_NO_KTLS */
|
||||
ret = 1;
|
||||
err:
|
||||
return ret;
|
||||
|
@ -1361,6 +1373,15 @@ int SSL_set_wfd(SSL *s, int fd)
|
|||
}
|
||||
BIO_set_fd(bio, fd, BIO_NOCLOSE);
|
||||
SSL_set0_wbio(s, bio);
|
||||
#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 /* OPENSSL_NO_KTLS */
|
||||
} else {
|
||||
BIO_up_ref(rbio);
|
||||
SSL_set0_wbio(s, rbio);
|
||||
|
@ -2186,6 +2207,10 @@ long SSL_ctrl(SSL *s, int cmd, long larg, void *parg)
|
|||
case SSL_CTRL_SET_MAX_SEND_FRAGMENT:
|
||||
if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH)
|
||||
return 0;
|
||||
#ifndef OPENSSL_NO_KTLS
|
||||
if (s->wbio != NULL && BIO_get_ktls_send(s->wbio))
|
||||
return 0;
|
||||
#endif /* OPENSSL_NO_KTLS */
|
||||
s->max_send_fragment = larg;
|
||||
if (s->max_send_fragment < s->split_send_fragment)
|
||||
s->split_send_fragment = s->max_send_fragment;
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
# include "internal/dane.h"
|
||||
# include "internal/refcount.h"
|
||||
# include "internal/tsan_assist.h"
|
||||
# include "internal/bio.h"
|
||||
|
||||
# ifdef OPENSSL_BUILD_SHLIBSSL
|
||||
# undef OPENSSL_EXTERN
|
||||
|
|
71
ssl/t1_enc.c
71
ssl/t1_enc.c
|
@ -10,10 +10,14 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include "ssl_locl.h"
|
||||
#include "record/record_locl.h"
|
||||
#include "internal/ktls.h"
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/comp.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/kdf.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/obj_mac.h>
|
||||
|
||||
/* seed1 through seed5 are concatenated */
|
||||
static int tls1_PRF(SSL *s,
|
||||
|
@ -98,6 +102,11 @@ int tls1_change_cipher_state(SSL *s, int which)
|
|||
EVP_PKEY *mac_key;
|
||||
size_t n, i, j, k, cl;
|
||||
int reuse_dd = 0;
|
||||
#ifndef OPENSSL_NO_KTLS
|
||||
struct tls12_crypto_info_aes_gcm_128 crypto_info;
|
||||
BIO *wbio;
|
||||
unsigned char geniv[12];
|
||||
#endif
|
||||
|
||||
c = s->s3->tmp.new_sym_enc;
|
||||
m = s->s3->tmp.new_hash;
|
||||
|
@ -319,6 +328,68 @@ int tls1_change_cipher_state(SSL *s, int which)
|
|||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
#ifndef OPENSSL_NO_KTLS
|
||||
if (s->compress)
|
||||
goto skip_ktls;
|
||||
|
||||
if ((which & SSL3_CC_READ) ||
|
||||
((which & SSL3_CC_WRITE) && (s->mode & SSL_MODE_NO_KTLS_TX)))
|
||||
goto skip_ktls;
|
||||
|
||||
/* ktls supports only the maximum fragment size */
|
||||
if (ssl_get_max_send_fragment(s) != SSL3_RT_MAX_PLAIN_LENGTH)
|
||||
goto skip_ktls;
|
||||
|
||||
/* check that cipher is AES_GCM_128 */
|
||||
if (EVP_CIPHER_nid(c) != NID_aes_128_gcm
|
||||
|| EVP_CIPHER_mode(c) != EVP_CIPH_GCM_MODE
|
||||
|| EVP_CIPHER_key_length(c) != TLS_CIPHER_AES_GCM_128_KEY_SIZE)
|
||||
goto skip_ktls;
|
||||
|
||||
/* check version is 1.2 */
|
||||
if (s->version != TLS1_2_VERSION)
|
||||
goto skip_ktls;
|
||||
|
||||
wbio = s->wbio;
|
||||
if (!ossl_assert(wbio != NULL)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* All future data will get encrypted by ktls. Flush the BIO or skip ktls */
|
||||
if (BIO_flush(wbio) <= 0)
|
||||
goto skip_ktls;
|
||||
|
||||
/* ktls doesn't support renegotiation */
|
||||
if (BIO_get_ktls_send(s->wbio)) {
|
||||
SSLfatal(s, SSL_AD_NO_RENEGOTIATION, SSL_F_TLS1_CHANGE_CIPHER_STATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
memset(&crypto_info, 0, sizeof(crypto_info));
|
||||
crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_128;
|
||||
crypto_info.info.version = s->version;
|
||||
|
||||
EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_GET_IV,
|
||||
EVP_GCM_TLS_FIXED_IV_LEN + EVP_GCM_TLS_EXPLICIT_IV_LEN,
|
||||
geniv);
|
||||
memcpy(crypto_info.iv, geniv + EVP_GCM_TLS_FIXED_IV_LEN,
|
||||
TLS_CIPHER_AES_GCM_128_IV_SIZE);
|
||||
memcpy(crypto_info.salt, geniv, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
|
||||
memcpy(crypto_info.key, key, EVP_CIPHER_key_length(c));
|
||||
memcpy(crypto_info.rec_seq, &s->rlayer.write_sequence,
|
||||
TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
|
||||
|
||||
/* ktls works with user provided buffers directly */
|
||||
if (BIO_set_ktls(wbio, &crypto_info, which & SSL3_CC_WRITE)) {
|
||||
ssl3_release_write_buffer(s);
|
||||
SSL_set_options(s, SSL_OP_NO_RENEGOTIATION);
|
||||
}
|
||||
|
||||
skip_ktls:
|
||||
#endif /* OPENSSL_NO_KTLS */
|
||||
s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
|
||||
|
||||
#ifdef SSL_DEBUG
|
||||
|
|
|
@ -108,6 +108,7 @@ BIO_get_buffer_num_lines define
|
|||
BIO_get_cipher_ctx define
|
||||
BIO_get_cipher_status define
|
||||
BIO_get_close define
|
||||
BIO_get_ktls_send define
|
||||
BIO_get_conn_address define
|
||||
BIO_get_conn_hostname define
|
||||
BIO_get_conn_port define
|
||||
|
|
Loading…
Reference in a new issue