[openssl-dev] [RFC 2/4] bio: Linux TLS Offload
Boris Pismenny
borisp at mellanox.com
Wed Jun 7 12:35:47 UTC 2017
Add support for Linux TLS offload in the BIO layer
and specifically in bss_sock.c.
Change-Id: I64e08da83c595a9067a3c7de80f73408010fcde6
Signed-off-by: Boris Pismenny <borisp at mellanox.com>
---
crypto/bio/bss_sock.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++-
include/openssl/bio.h | 32 ++++++++++++++++++
2 files changed, 124 insertions(+), 1 deletion(-)
diff --git a/crypto/bio/bss_sock.c b/crypto/bio/bss_sock.c
index 570e898..5f02d04 100644
--- a/crypto/bio/bss_sock.c
+++ b/crypto/bio/bss_sock.c
@@ -27,6 +27,11 @@
# define sock_puts SockPuts
# endif
+#if defined(OPENSSL_LINUX_TLS)
+ #include "netinet/tcp.h"
+#endif
+
+
static int sock_write(BIO *h, const char *buf, int num);
static int sock_read(BIO *h, char *buf, int size);
static int sock_puts(BIO *h, const char *str);
@@ -56,11 +61,21 @@ const BIO_METHOD *BIO_s_socket(void)
BIO *BIO_new_socket(int fd, int close_flag)
{
BIO *ret;
+ int rc;
ret = BIO_new(BIO_s_socket());
if (ret == NULL)
return (NULL);
BIO_set_fd(ret, fd, close_flag);
+#ifdef OPENSSL_LINUX_TLS
+ rc = setsockopt(fd, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));
+#ifdef SSL_DEBUG
+ if (rc) {
+ printf("setsockopt failed %d\n", errno);
+ }
+#endif
+
+# endif
return (ret);
}
@@ -103,12 +118,54 @@ static int sock_read(BIO *b, char *out, int outl)
return (ret);
}
+static int 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);
+}
+
static int sock_write(BIO *b, const char *in, int inl)
{
int ret;
clear_socket_error();
- ret = writesocket(b->num, in, inl);
+ if (BIO_should_offload_tx_ctrl_msg_flag(b)) {
+ unsigned char record_type = (unsigned char)b->ptr;
+
+#ifdef SSL_DEBUG
+ printf("\nsending ctrl msg\n");
+#endif
+ BIO_clear_offload_tx_ctrl_msg_flag(b);
+ ret = send_ctrl_message(b->num, record_type, in, inl);
+ if (ret >= 0) {
+ ret = inl;
+ }
+ } else {
+#ifdef SSL_DEBUG
+ printf("\nsending data msg %p %d\n", b, b->flags);
+#endif
+ ret = writesocket(b->num, in, inl);
+ }
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (BIO_sock_should_retry(ret))
@@ -121,6 +178,9 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr)
{
long ret = 1;
int *ip;
+# ifdef OPENSSL_LINUX_TLS
+ struct tls12_crypto_info_aes_gcm_128 *crypto_info;
+# endif
switch (cmd) {
case BIO_C_SET_FD:
@@ -148,6 +208,37 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr)
case BIO_CTRL_FLUSH:
ret = 1;
break;
+# if defined(OPENSSL_LINUX_TLS)
+ case BIO_CTRL_SET_OFFLOAD_TX:
+ crypto_info = (struct tls12_crypto_info_aes_gcm_128 *)ptr;
+ ret = setsockopt(b->num, SOL_TLS, TLS_TX,
+ crypto_info, sizeof(*crypto_info));
+#ifdef SSL_DEBUG
+ printf("\nAttempt to offload...");
+#endif
+ if (!ret) {
+ BIO_set_offload_tx_flag(b);
+#ifdef SSL_DEBUG
+ printf("Success %p %p\n", b, &(b->flags));
+#endif
+ } else {
+#ifdef SSL_DEBUG
+ printf("Failed ret=%ld\n", ret);
+#endif
+ }
+ break;
+ case BIO_CTRL_GET_OFFLOAD_TX:
+ return BIO_should_offload_tx_flag(b);
+ case BIO_CTRL_SET_OFFLOAD_TX_CTRL_MSG:
+ BIO_set_offload_tx_ctrl_msg_flag(b);
+ b->ptr = (void *)num;
+ ret = 0;
+ break;
+ case BIO_CTRL_CLEAR_OFFLOAD_TX_CTRL_MSG:
+ BIO_clear_offload_tx_ctrl_msg_flag(b);
+ ret = 0;
+ break;
+# endif
default:
ret = 0;
break;
diff --git a/include/openssl/bio.h b/include/openssl/bio.h
index 31d41b4..c718627 100644
--- a/include/openssl/bio.h
+++ b/include/openssl/bio.h
@@ -146,6 +146,11 @@ extern "C" {
# define BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN 70
# endif
+# define BIO_CTRL_SET_OFFLOAD_TX 71
+# define BIO_CTRL_GET_OFFLOAD_TX 72
+# define BIO_CTRL_SET_OFFLOAD_TX_CTRL_MSG 73
+# define BIO_CTRL_CLEAR_OFFLOAD_TX_CTRL_MSG 74
+
/* modifiers */
# define BIO_FP_READ 0x02
# define BIO_FP_WRITE 0x04
@@ -175,6 +180,13 @@ extern "C" {
# define BIO_FLAGS_MEM_RDONLY 0x200
# define BIO_FLAGS_NONCLEAR_RST 0x400
+/*
+ * This is used with socket BIOs:
+ * BIO_FLAGS_OFFLOAD_TX means we are using offload with this BIO for TX.
+ * BIO_FLAGS_OFFLOAD_TX_CTRL_MSG means we are about to send a ctrl message next.
+ */
+# define BIO_FLAGS_OFFLOAD_TX 0x2000
+# define BIO_FLAGS_OFFLOAD_TX_CTRL_MSG 0x4000
typedef union bio_addr_st BIO_ADDR;
typedef struct bio_addrinfo_st BIO_ADDRINFO;
@@ -191,6 +203,18 @@ void BIO_clear_flags(BIO *b, int flags);
# define BIO_set_retry_write(b) \
BIO_set_flags(b, (BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY))
+/* Offload related controls and flags */
+# define BIO_set_offload_tx_flag(b) \
+ BIO_set_flags(b, BIO_FLAGS_OFFLOAD_TX)
+# define BIO_should_offload_tx_flag(b) \
+ BIO_test_flags(b, BIO_FLAGS_OFFLOAD_TX)
+# define BIO_set_offload_tx_ctrl_msg_flag(b) \
+ BIO_set_flags(b, BIO_FLAGS_OFFLOAD_TX_CTRL_MSG)
+# define BIO_should_offload_tx_ctrl_msg_flag(b) \
+ BIO_test_flags(b, (BIO_FLAGS_OFFLOAD_TX_CTRL_MSG))
+# define BIO_clear_offload_tx_ctrl_msg_flag(b) \
+ BIO_clear_flags(b, (BIO_FLAGS_OFFLOAD_TX_CTRL_MSG))
+
/* These are normally used internally in BIOs */
# define BIO_clear_retry_flags(b) \
BIO_clear_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY))
@@ -370,6 +394,14 @@ struct bio_dgram_sctp_prinfo {
# define BIO_get_conn_address(b) ((const BIO_ADDR *)BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,2,NULL))
# define BIO_get_conn_ip_family(b) BIO_ctrl(b,BIO_C_GET_CONNECT,3,NULL)
# define BIO_set_conn_mode(b,n) BIO_ctrl(b,BIO_C_SET_CONNECT_MODE,(n),NULL)
+# define BIO_set_offload_tx(b, keyblob) \
+ BIO_ctrl(b, BIO_CTRL_SET_OFFLOAD_TX, 0, keyblob)
+# define BIO_get_offload_tx(b) \
+ BIO_ctrl(b, BIO_CTRL_GET_OFFLOAD_TX, 0, NULL)
+# define BIO_set_offload_tx_ctrl_msg(b, record_type) \
+ BIO_ctrl(b, BIO_CTRL_SET_OFFLOAD_TX_CTRL_MSG, record_type, NULL)
+# define BIO_clear_offload_tx_ctrl_msg(b) \
+ BIO_ctrl(b, BIO_CTRL_CLEAR_OFFLOAD_TX_CTRL_MSG, 0, NULL)
/* BIO_s_accept() */
# define BIO_set_accept_name(b,name) BIO_ctrl(b,BIO_C_SET_ACCEPT,0,(char *)name)
--
1.8.3.1
More information about the openssl-dev
mailing list