Add support for Linux TLS offload in the BIO layer and specifically in bss_sock.c.
Change-Id: I64e08da83c595a9067a3c7de80f73408010fcde6 Signed-off-by: Boris Pismenny <bor...@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 -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev