diff options
author | Boris Pismenny <borisp@mellanox.com> | 2018-01-31 16:43:35 +0200 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2018-12-07 11:25:45 +0000 |
commit | fe3ad3aee37f7bcb52c647a4f1c8a6f60360d095 (patch) | |
tree | 27e17259b6019ec922078fcf15c63ee5671afece /include/internal/ktls.h | |
parent | a86003162138031137727147c9b642d99db434b1 (diff) |
Linux ktls infrastructure
Introduce a compatability layer that exposes the required structures
and constants for supporting ktls.
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 'include/internal/ktls.h')
-rw-r--r-- | include/internal/ktls.h | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/include/internal/ktls.h b/include/internal/ktls.h new file mode 100644 index 0000000000..542acf3785 --- /dev/null +++ b/include/internal/ktls.h @@ -0,0 +1,147 @@ +/* + * 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(OPENSSL_SYS_LINUX) +# include <linux/version.h> + +# 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 data path" +# endif + +# define TLS_TX 1 + +# 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; +} + +# else /* KERNEL_VERSION */ + +# include <netinet/tcp.h> +# include <linux/tls.h> +# include <linux/socket.h> + +# ifndef SOL_TLS +# define SOL_TLS 282 +# endif + +# ifndef TCP_ULP +# define TCP_ULP 31 +# 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. + */ +static ossl_inline int ktls_start(int fd, + struct tls12_crypto_info_aes_gcm_128 + *crypto_info, size_t len, int is_tx) +{ + if (is_tx) + return setsockopt(fd, SOL_TLS, TLS_TX, crypto_info, + sizeof(*crypto_info)) ? 0 : 1; + else + return 0; +} + +/* + * 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 = { 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 = 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); +} + +# endif /* KERNEL_VERSION */ +# endif /* OPENSSL_SYS_LINUX */ +# endif /* HEADER_INTERNAL_KTLS */ +#endif /* OPENSSL_NO_KTLS */ |