diff options
author | Boris Pismenny <borisp@mellanox.com> | 2017-06-01 08:25:47 +0200 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2018-12-07 12:25:45 +0100 |
commit | 50ec750567e056fcecff2344c2d9044d81cc731b (patch) | |
tree | c4da98b9c0a4fa6f528a74914fde3d21bc38b80a /ssl/t1_enc.c | |
parent | evp/e_aes: Expose IV (diff) | |
download | openssl-50ec750567e056fcecff2344c2d9044d81cc731b.tar.xz openssl-50ec750567e056fcecff2344c2d9044d81cc731b.zip |
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)
Diffstat (limited to 'ssl/t1_enc.c')
-rw-r--r-- | ssl/t1_enc.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index 2313afd3b7..adcc62619f 100644 --- a/ssl/t1_enc.c +++ b/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 |