Index: security/Makefile =================================================================== --- security/Makefile +++ security/Makefile @@ -466,6 +466,7 @@ SUBDIR += openssh-askpass SUBDIR += openssh-portable SUBDIR += openssl + SUBDIR += openssl-chelsio SUBDIR += openssl-unsafe SUBDIR += openssl111 SUBDIR += openssl_tpm_engine Index: security/openssl-chelsio/Makefile =================================================================== --- /dev/null +++ security/openssl-chelsio/Makefile @@ -0,0 +1,157 @@ +# Created by: Dirk Froemberg +# $FreeBSD$ + +PORTNAME= openssl +DISTVERSION= 1.1.1 +PORTREVISION= 3 +CATEGORIES= security devel +MASTER_SITES= https://www.openssl.org/source/ \ + ftp://ftp.cert.dfn.de/pub/tools/net/openssl/source/ +PKGNAMESUFFIX= -chelsio + +MAINTAINER= jhb@FreeBSD.org +COMMENT= TLSv1.3 capable SSL and crypto library supporting Chelsio TLS offload + +LICENSE= OpenSSL +LICENSE_FILE= ${WRKSRC}/LICENSE + +HAS_CONFIGURE= yes +CONFIGURE_SCRIPT= config +CONFIGURE_ENV= PERL="${PERL}" +CONFIGURE_ARGS= --openssldir=${OPENSSLDIR} +CONFIGURE_ARGS+= --prefix=${PREFIX}/openssl-chelsio + +USES= cpe perl5 +USE_PERL5= build +TEST_TARGET= test + +LDFLAGS_i386= -Wl,-znotext +#LDFLAGS= ${LDFLAGS_${ARCH}} + +MAKE_ARGS+= WHOLE_ARCHIVE_FLAG=--whole-archive CNF_LDFLAGS="${LDFLAGS}" +MAKE_ENV+= LIBRPATH="${PREFIX}/openssl-chelsio/lib" GREP_OPTIONS= +MAKE_ENV+= SHLIBVER=${OPENSSL_SHLIBVER} + +OPTIONS_GROUP= CIPHERS HASHES OPTIMIZE PROTOCOLS +OPTIONS_GROUP_CIPHERS= ARIA DES GOST IDEA SM2 SM3 SM4 RC2 RC4 RC5 +OPTIONS_GROUP_HASHES= MD2 MD4 MDC2 RMD160 +OPTIONS_GROUP_OPTIMIZE= ASM SSE2 THREADS +OPTIONS_DEFINE_i386= I386 +OPTIONS_GROUP_PROTOCOLS=NEXTPROTONEG SCTP SSL3 TLS1 TLS1_1 TLS1_2 + +OPTIONS_DEFINE= ASYNC CT RFC3779 ZLIB + +OPTIONS_DEFAULT=ASM ASYNC CT GOST DES EC MD4 NEXTPROTONEG RC2 RC4 \ + RMD160 SCTP SSE2 THREADS TLS1 TLS1_1 TLS1_2 + +OPTIONS_GROUP_OPTIMIZE_amd64= EC + +.if ${MACHINE_ARCH} == "amd64" +OPTIONS_GROUP_OPTIMIZE+= EC +.elif ${MACHINE_ARCH} == "mips64el" +OPTIONS_GROUP_OPTIMIZE+= EC +.endif + +OPTIONS_SUB= yes + +ARIA_DESC= ARIA (South Korean standard) +ASM_DESC= Assembler code +ASYNC_DESC= Asynchronous mode +CIPHERS_DESC= Block Cipher Support +CT_DESC= Certificate Transparency Support +DES_DESC= (Triple) Data Encryption Standard +EC_DESC= Optimize NIST elliptic curves +GOST_DESC= GOST (Russian standard) +HASHES_DESC= Hash Function Support +I386_DESC= i386 (instead of i486+) +IDEA_DESC= International Data Encryption Algorithm +MD2_DESC= MD2 (obsolete) +MD4_DESC= MD4 (unsafe) +MDC2_DESC= MDC-2 (patented, requires DES) +NEXTPROTONEG_DESC= Next Protocol Negotiation (SPDY) +OPTIMIZE_DESC= Optimizations +PROTOCOLS_DESC= Protocol Support +RC2_DESC= RC2 (unsafe) +RC4_DESC= RC4 (unsafe) +RC5_DESC= RC5 (patented) +RMD160_DESC= RIPEMD-160 +RFC3779_DESC= RFC3779 support (BGP) +SCTP_DESC= SCTP (Stream Control Transmission) +SM2_DESC= SM2 (Chinese standard) +SM3_DESC= SM3 (Chinese standard) +SM4_DESC= SM4 (Chinese standard) +SSE2_DESC= Runtime SSE2 detection +SSL3_DESC= SSLv3 (unsafe) +TLS1_DESC= TLSv1.0 (requires TLS1_1, TLS1_2) +TLS1_1_DESC= TLSv1.1 (requires TLS1_2) +TLS1_2_DESC= TLSv1.2 +ZLIB_DESC= zlib compression support + +# Upstream default disabled options +.for _option in md2 rc5 sctp ssl3 zlib +${_option:tu}_CONFIGURE_ON= enable-${_option} +.endfor + +# Upstream default enabled options +.for _option in aria asm async ct des gost idea md4 mdc2 nextprotoneg \ + rfc3779 rmd160 shared sm2 sm3 sm4 sse2 threads tls1 tls1_1 tls1_2 +${_option:tu}_CONFIGURE_OFF= no-${_option} +.endfor + +MDC2_IMPLIES= DES +TLS1_IMPLIES= TLS1_1 +TLS1_1_IMPLIES= TLS1_2 + +EC_CONFIGURE_ON= enable-ec_nistp_64_gcc_128 +I386_CONFIGURE_ON= 386 +SSL3_CONFIGURE_ON+= enable-ssl3-method +ZLIB_CONFIGURE_ON= zlib-dynamic + +.include +.if ${PREFIX} == /usr +IGNORE= the OpenSSL port can not be installed over the base version +.endif + +OPENSSLDIR= ${PREFIX}/openssl-chelsio +PLIST_SUB+= OPENSSLDIR=${OPENSSLDIR:S=^${PREFIX}/==} +PLIST_SUB+= SHLIBVER=${OPENSSL_SHLIBVER} +CFLAGS+= -DCHELSIO_TLS_OFFLOAD -g + +.include "version.mk" + +.if ${PORT_OPTIONS:MASM} +BROKEN_sparc64= option ASM generates illegal instructions +.endif + +post-patch: + ${REINPLACE_CMD} \ + -e 's|^MANDIR=.*$$|MANDIR=$$(INSTALLTOP)/man|' \ + -e 's| install_html_docs$$||' \ + -e 's|$$(LIBDIR)/pkgconfig|libdata/pkgconfig|g' \ + ${WRKSRC}/Configurations/unix-Makefile.tmpl + ${REINPLACE_CMD} -e 's|\^GNU ld|GNU|' ${WRKSRC}/Configurations/shared-info.pl + +post-configure: + ${REINPLACE_CMD} \ + -e 's|SHLIB_VERSION_NUMBER=1.1|SHLIB_VERSION_NUMBER=${OPENSSL_SHLIBVER}|' \ + ${WRKSRC}/Makefile + ${REINPLACE_CMD} \ + -e 's|SHLIB_VERSION_NUMBER "1.1"|SHLIB_VERSION_NUMBER "${OPENSSL_SHLIBVER}"|' \ + ${WRKSRC}/include/openssl/opensslv.h + +do-install: + ${MKDIR} ${STAGEDIR}${PREFIX}/openssl-chelsio/lib/engines-1.1 +.for i in libcrypto libssl + ${INSTALL_DATA} ${WRKSRC}/$i.so.${OPENSSL_SHLIBVER} ${STAGEDIR}${PREFIX}/openssl-chelsio/lib +# ${STRIP_CMD} ${STAGEDIR}${PREFIX}/openssl-chelsio/lib/$i.so.${OPENSSL_SHLIBVER} +.endfor +.for i in capi padlock + ${INSTALL_DATA} ${WRKSRC}/engines/${i}.so ${STAGEDIR}${PREFIX}/openssl-chelsio/lib/engines-1.1 + ${STRIP_CMD} ${STAGEDIR}${PREFIX}/openssl-chelsio/lib/engines-1.1/${i}.so +.endfor + ${MKDIR} ${STAGEDIR}${OPENSSLDIR}/private + ${MKDIR} ${STAGEDIR}${OPENSSLDIR}/certs + ${INSTALL_DATA} ${WRKSRC}/apps/openssl.cnf ${STAGEDIR}${OPENSSLDIR}/openssl.cnf.dist + ${INSTALL_DATA} ${WRKSRC}/apps/ct_log_list.cnf ${STAGEDIR}${OPENSSLDIR}/ct_log_list.cnf.dist + +.include Index: security/openssl-chelsio/distinfo =================================================================== --- /dev/null +++ security/openssl-chelsio/distinfo @@ -0,0 +1,3 @@ +TIMESTAMP = 1536741340 +SHA256 (openssl-1.1.1.tar.gz) = 2836875a0f89c03d0fdf483941512613a50cfb421d6fd94b9f41d7279d586a3d +SIZE (openssl-1.1.1.tar.gz) = 8337920 Index: security/openssl-chelsio/files/patch-CVE-2018-0734 =================================================================== --- /dev/null +++ security/openssl-chelsio/files/patch-CVE-2018-0734 @@ -0,0 +1,98 @@ +Timing vulnerability in DSA signature generation (CVE-2018-0734). + +Avoid a timing attack that leaks information via a side channel that +triggers when a BN is resized. Increasing the size of the BNs +prior to doing anything with them suppresses the attack. + +Thanks due to Samuel Weiser for finding and locating this. + +Reviewed-by: Bernd Edlinger +(Merged from #7486) + +(cherry picked from commit a9cfb8c) + +https://github.com/openssl/openssl/commit/8abfe72e8c1de1b95f50aa0d9134803b4d00070f +--- crypto/dsa/dsa_ossl.c.orig 2018-09-11 12:48:21 UTC ++++ crypto/dsa/dsa_ossl.c +@@ -9,6 +9,7 @@ + + #include + #include "internal/cryptlib.h" ++#include "internal/bn_int.h" + #include + #include + #include "dsa_locl.h" +@@ -178,9 +179,9 @@ static int dsa_sign_setup(DSA *dsa, BN_C + { + BN_CTX *ctx = NULL; + BIGNUM *k, *kinv = NULL, *r = *rp; +- BIGNUM *l, *m; ++ BIGNUM *l; + int ret = 0; +- int q_bits; ++ int q_bits, q_words; + + if (!dsa->p || !dsa->q || !dsa->g) { + DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_MISSING_PARAMETERS); +@@ -189,8 +190,7 @@ static int dsa_sign_setup(DSA *dsa, BN_C + + k = BN_new(); + l = BN_new(); +- m = BN_new(); +- if (k == NULL || l == NULL || m == NULL) ++ if (k == NULL || l == NULL) + goto err; + + if (ctx_in == NULL) { +@@ -201,9 +201,9 @@ static int dsa_sign_setup(DSA *dsa, BN_C + + /* Preallocate space */ + q_bits = BN_num_bits(dsa->q); +- if (!BN_set_bit(k, q_bits) +- || !BN_set_bit(l, q_bits) +- || !BN_set_bit(m, q_bits)) ++ q_words = bn_get_top(dsa->q); ++ if (!bn_wexpand(k, q_words + 2) ++ || !bn_wexpand(l, q_words + 2)) + goto err; + + /* Get random k */ +@@ -238,14 +238,17 @@ static int dsa_sign_setup(DSA *dsa, BN_C + * small timing information leakage. We then choose the sum that is + * one bit longer than the modulus. + * +- * TODO: revisit the BN_copy aiming for a memory access agnostic +- * conditional copy. ++ * There are some concerns about the efficacy of doing this. More ++ * specificly refer to the discussion starting with: ++ * https://github.com/openssl/openssl/pull/7486#discussion_r228323705 ++ * The fix is to rework BN so these gymnastics aren't required. + */ + if (!BN_add(l, k, dsa->q) +- || !BN_add(m, l, dsa->q) +- || !BN_copy(k, BN_num_bits(l) > q_bits ? l : m)) ++ || !BN_add(k, l, dsa->q)) + goto err; + ++ BN_consttime_swap(BN_is_bit_set(l, q_bits), k, l, q_words + 2); ++ + if ((dsa)->meth->bn_mod_exp != NULL) { + if (!dsa->meth->bn_mod_exp(dsa, r, dsa->g, k, dsa->p, ctx, + dsa->method_mont_p)) +@@ -258,7 +261,7 @@ static int dsa_sign_setup(DSA *dsa, BN_C + if (!BN_mod(r, r, dsa->q, ctx)) + goto err; + +- /* Compute part of 's = inv(k) (m + xr) mod q' */ ++ /* Compute part of 's = inv(k) (m + xr) mod q' */ + if ((kinv = BN_mod_inverse(NULL, k, dsa->q, ctx)) == NULL) + goto err; + +@@ -273,7 +276,6 @@ static int dsa_sign_setup(DSA *dsa, BN_C + BN_CTX_free(ctx); + BN_clear_free(k); + BN_clear_free(l); +- BN_clear_free(m); + return ret; + } + Index: security/openssl-chelsio/files/patch-CVE-2018-0735 =================================================================== --- /dev/null +++ security/openssl-chelsio/files/patch-CVE-2018-0735 @@ -0,0 +1,33 @@ +Timing vulnerability in ECDSA signature generation (CVE-2018-0735) + +Preallocate an extra limb for some of the big numbers to avoid a reallocation +that can potentially provide a side channel. + +Reviewed-by: Bernd Edlinger +(Merged from #7486) + +(cherry picked from commit 99540ec) + +https://www.openssl.org/news/secadv/20181029.txt +--- crypto/ec/ec_mult.c.orig 2018-09-11 12:48:21 UTC ++++ crypto/ec/ec_mult.c +@@ -206,8 +206,8 @@ int ec_scalar_mul_ladder(const EC_GROUP + */ + cardinality_bits = BN_num_bits(cardinality); + group_top = bn_get_top(cardinality); +- if ((bn_wexpand(k, group_top + 1) == NULL) +- || (bn_wexpand(lambda, group_top + 1) == NULL)) { ++ if ((bn_wexpand(k, group_top + 2) == NULL) ++ || (bn_wexpand(lambda, group_top + 2) == NULL)) { + ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB); + goto err; + } +@@ -244,7 +244,7 @@ int ec_scalar_mul_ladder(const EC_GROUP + * k := scalar + 2*cardinality + */ + kbit = BN_is_bit_set(lambda, cardinality_bits); +- BN_consttime_swap(kbit, k, lambda, group_top + 1); ++ BN_consttime_swap(kbit, k, lambda, group_top + 2); + + group_top = bn_get_top(group->field); + if ((bn_wexpand(s->X, group_top) == NULL) Index: security/openssl-chelsio/files/patch-chelsio-toe =================================================================== --- /dev/null +++ security/openssl-chelsio/files/patch-chelsio-toe @@ -0,0 +1,1051 @@ +diff --git crypto/bio/bss_conn.c crypto/bio/bss_conn.c +index e9673fe783..20131de7e0 100644 +--- crypto/bio/bss_conn.c ++++ crypto/bio/bss_conn.c +@@ -11,6 +11,7 @@ + #include + + #include "bio_lcl.h" ++#include "ssl/ssl_ofld.h" + + #ifndef OPENSSL_NO_SOCK + +@@ -179,6 +180,28 @@ static int conn_state(BIO *b, BIO_CONNECT *c) + goto exit_loop; + } else { + c->state = BIO_CONN_S_OK; ++#ifdef CHELSIO_TLS_OFFLOAD ++ int mode, rc; ++#ifdef __linux__ ++ rc = ioctl(b->num, IOCTL_TLSOM_GET_TLS_TOM, &mode); ++ if (!rc && mode) ++ BIO_set_chofld_flag(b); ++#else ++ socklen_t optlen; ++ optlen = sizeof(mode); ++ rc = getsockopt(b->num, IPPROTO_TCP, TCP_TLSOM_GET_TLS_TOM, ++ &mode, &optlen); ++ if (rc == 0) { ++ switch (mode) { ++ case TLS_TOM_BOTH: ++ case TLS_TOM_TXONLY: ++ /* For TXONLY, chssl_program_hwkey_context will DTRT. */ ++ BIO_set_chofld_flag(b); ++ break; ++ } ++ } ++#endif ++#endif + } + break; + +@@ -343,6 +366,9 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr) + const char **pptr = NULL; + long ret = 1; + BIO_CONNECT *data; ++#ifdef CHELSIO_TLS_OFFLOAD ++ struct tls_key_context *key_context; ++#endif + + data = (BIO_CONNECT *)b->ptr; + +@@ -488,6 +514,37 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr) + *fptr = data->info_callback; + } + 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; ++ case BIO_CTRL_GET_OFFLOAD_RX: ++ return BIO_should_offload_rx_flag(b); ++#ifdef CHELSIO_TLS_OFFLOAD ++ case BIO_CTRL_SET_OFFLOAD_KEY: ++ key_context = (struct tls_key_context *)ptr; ++#ifdef __linux__ ++ ret = ioctl(b->num, IOCTL_TLSOM_SET_TLS_CONTEXT, key_context); ++#else ++ ret = setsockopt(b->num, IPPROTO_TCP, TCP_TLSOM_SET_TLS_CONTEXT, ++ key_context, sizeof(*key_context)); ++#endif ++ break; ++ case BIO_CTRL_SET_OFFLOAD_CLEAR_KEY: ++#ifdef __linux__ ++ ret = ioctl(b->num, IOCTL_TLSOM_CLR_TLS_TOM); ++#else ++ ret = setsockopt(b->num, IPPROTO_TCP, TCP_TLSOM_CLR_TLS_TOM, NULL, 0); ++#endif ++ break; ++#endif + default: + ret = 0; + break; +diff --git crypto/bio/bss_sock.c crypto/bio/bss_sock.c +index ad38453201..4a0e2a46d4 100644 +--- crypto/bio/bss_sock.c ++++ crypto/bio/bss_sock.c +@@ -11,6 +11,7 @@ + #include + #include "bio_lcl.h" + #include "internal/cryptlib.h" ++#include "ssl/ssl_ofld.h" + + #ifndef OPENSSL_NO_SOCK + +@@ -124,6 +125,9 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) + { + long ret = 1; + int *ip; ++#ifdef CHELSIO_TLS_OFFLOAD ++ struct tls_key_context *key_context; ++#endif + + switch (cmd) { + case BIO_C_SET_FD: +@@ -131,6 +135,30 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) + b->num = *((int *)ptr); + b->shutdown = (int)num; + b->init = 1; ++#ifdef CHELSIO_TLS_OFFLOAD ++ { ++ int mode, rc; ++#ifdef __linux__ ++ rc = ioctl(b->num, IOCTL_TLSOM_GET_TLS_TOM, &mode); ++ if (!rc && mode) ++ BIO_set_chofld_flag(b); ++#else ++ socklen_t optlen; ++ optlen = sizeof(mode); ++ rc = getsockopt(b->num, IPPROTO_TCP, TCP_TLSOM_GET_TLS_TOM, &mode, ++ &optlen); ++ if (rc == 0) { ++ switch (mode) { ++ case TLS_TOM_BOTH: ++ case TLS_TOM_TXONLY: ++ /* For TXONLY, chssl_program_hwkey_context will DTRT. */ ++ BIO_set_chofld_flag(b); ++ break; ++ } ++ } ++#endif ++ } ++#endif + break; + case BIO_C_GET_FD: + if (b->init) { +@@ -151,6 +179,37 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) + case BIO_CTRL_FLUSH: + ret = 1; + 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; ++ case BIO_CTRL_GET_OFFLOAD_RX: ++ return BIO_should_offload_rx_flag(b); ++#ifdef CHELSIO_TLS_OFFLOAD ++ case BIO_CTRL_SET_OFFLOAD_KEY: ++ key_context = (struct tls_key_context *)ptr; ++#ifdef __linux__ ++ ret = ioctl(b->num, IOCTL_TLSOM_SET_TLS_CONTEXT, key_context); ++#else ++ ret = setsockopt(b->num, IPPROTO_TCP, TCP_TLSOM_SET_TLS_CONTEXT, ++ key_context, sizeof(*key_context)); ++#endif ++ break; ++ case BIO_CTRL_SET_OFFLOAD_CLEAR_KEY: ++#ifdef __linux__ ++ ret = ioctl(b->num, IOCTL_TLSOM_CLR_TLS_TOM); ++#else ++ ret = setsockopt(b->num, IPPROTO_TCP, TCP_TLSOM_CLR_TLS_TOM, NULL, 0); ++#endif ++ break; ++#endif + default: + ret = 0; + break; +diff --git include/openssl/bio.h include/openssl/bio.h +index 2888b42da8..38a3cabad1 100644 +--- include/openssl/bio.h ++++ include/openssl/bio.h +@@ -144,6 +144,14 @@ extern "C" { + # endif + + # define BIO_CTRL_DGRAM_SET_PEEK_MODE 71 ++# define BIO_CTRL_SET_OFFLOAD_TX 72 ++# define BIO_CTRL_GET_OFFLOAD_TX 73 ++# define BIO_CTRL_SET_OFFLOAD_TX_CTRL_MSG 74 ++# define BIO_CTRL_CLEAR_OFFLOAD_TX_CTRL_MSG 75 ++# define BIO_CTRL_SET_OFFLOAD_RX 76 ++# define BIO_CTRL_GET_OFFLOAD_RX 77 ++# define BIO_CTRL_SET_OFFLOAD_KEY 78 ++# define BIO_CTRL_SET_OFFLOAD_CLEAR_KEY 79 + + /* modifiers */ + # define BIO_FP_READ 0x02 +@@ -174,6 +182,16 @@ 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 ++#define BIO_FLAGS_OFFLOAD_RX 0x8000 ++#define BIO_FLAGS_CHOFLD_INLINE 0x10000 ++ + typedef union bio_addr_st BIO_ADDR; + typedef struct bio_addrinfo_st BIO_ADDRINFO; + +@@ -189,6 +207,25 @@ void BIO_clear_flags(BIO *b, int flags); + BIO_set_flags(b, (BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY)) + # 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)) ++# define BIO_set_offload_rx_flag(b) \ ++ BIO_set_flags(b, BIO_FLAGS_OFFLOAD_RX) ++# define BIO_should_offload_rx_flag(b) \ ++ BIO_test_flags(b, BIO_FLAGS_OFFLOAD_RX) ++# define BIO_set_chofld_flag(b) \ ++ BIO_set_flags(b, BIO_FLAGS_CHOFLD_INLINE) ++# define BIO_get_chofld_flag(b) \ ++ BIO_test_flags(b, BIO_FLAGS_CHOFLD_INLINE) + + /* These are normally used internally in BIOs */ + # define BIO_clear_retry_flags(b) \ +@@ -380,6 +417,22 @@ struct bio_dgram_sctp_prinfo { + # define BIO_get_conn_address(b) ((const BIO_ADDR *)BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,2)) + # 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) ++# define BIO_set_offload_rx(b, keyblob) \ ++ BIO_ctrl(b, BIO_CTRL_SET_OFFLOAD_RX, 0, keyblob) ++# define BIO_get_offload_rx(b) \ ++ BIO_ctrl(b, BIO_CTRL_GET_OFFLOAD_RX, 0, NULL) ++# define BIO_set_offload_key(b, keyblob) \ ++ BIO_ctrl(b, BIO_CTRL_SET_OFFLOAD_KEY, 0, keyblob) ++# define BIO_set_offload_clear_key(b) \ ++ BIO_ctrl(b, BIO_CTRL_SET_OFFLOAD_CLEAR_KEY, 0, NULL) + + /* BIO_s_accept() */ + # define BIO_set_accept_name(b,name) BIO_ctrl(b,BIO_C_SET_ACCEPT,0, \ +diff --git include/openssl/ssl.h include/openssl/ssl.h +index 0a18a43544..82ac6fd093 100644 +--- include/openssl/ssl.h ++++ include/openssl/ssl.h +@@ -1069,6 +1069,7 @@ int SSL_is_init_finished(const SSL *s); + # define SSL_ST_READ_HEADER 0xF0 + # define SSL_ST_READ_BODY 0xF1 + # define SSL_ST_READ_DONE 0xF2 ++# define SSL_ST_READ_ERROR 0xF3 + + /*- + * Obtain latest Finished message +diff --git ssl/build.info ssl/build.info +index bb2f1deb53..bbd8c2db7f 100644 +--- ssl/build.info ++++ ssl/build.info +@@ -11,5 +11,6 @@ SOURCE[../libssl]=\ + ssl_ciph.c ssl_stat.c ssl_rsa.c \ + ssl_asn1.c ssl_txt.c ssl_init.c ssl_conf.c ssl_mcnf.c \ + bio_ssl.c ssl_err.c tls_srp.c t1_trce.c ssl_utst.c \ ++ ssl_ofld.c \ + record/ssl3_buffer.c record/ssl3_record.c record/dtls1_bitmap.c \ + statem/statem.c record/ssl3_record_tls13.c +diff --git ssl/record/rec_layer_s3.c ssl/record/rec_layer_s3.c +index 6d495715b2..1ce19d31e4 100644 +--- ssl/record/rec_layer_s3.c ++++ ssl/record/rec_layer_s3.c +@@ -797,7 +797,8 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf, + } + + /* Explicit IV length, block ciphers appropriate version flag */ +- if (s->enc_write_ctx && SSL_USE_EXPLICIT_IV(s) && !SSL_TREAT_AS_TLS13(s)) { ++ if (s->enc_write_ctx && SSL_USE_EXPLICIT_IV(s) && !SSL_TREAT_AS_TLS13(s) ++ && !BIO_get_offload_tx(s->wbio)) { + int mode = EVP_CIPHER_CTX_mode(s->enc_write_ctx); + if (mode == EVP_CIPH_CBC_MODE) { + /* TODO(size_t): Convert me */ +@@ -951,7 +952,8 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf, + * in the wb->buf + */ + +- if (!SSL_WRITE_ETM(s) && mac_size != 0) { ++ if (!SSL_WRITE_ETM(s) && mac_size != 0 ++ && !BIO_get_offload_tx(s->wbio)) { + unsigned char *mac; + + if (!WPACKET_allocate_bytes(thispkt, mac_size, &mac) +@@ -999,7 +1001,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf, + } + goto err; + } +- } else { ++ } else if (!BIO_get_offload_tx(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, +@@ -1149,6 +1151,9 @@ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, size_t len, + (unsigned int)SSL3_BUFFER_get_left(&wb[currbuf])); + if (i >= 0) + tmpwrit = i; ++ ++ if (BIO_get_offload_tx(s->wbio) && type != SSL3_RT_APPLICATION_DATA) ++ (void)BIO_flush(s->wbio); + } else { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_WRITE_PENDING, + SSL_R_BIO_NOT_SET); +diff --git ssl/record/ssl3_record.c ssl/record/ssl3_record.c +index e59ac5a676..26c8c5f692 100644 +--- ssl/record/ssl3_record.c ++++ ssl/record/ssl3_record.c +@@ -225,6 +225,11 @@ int ssl3_get_record(SSL *s) + ERR_R_INTERNAL_ERROR); + return -1; + } ++ ++ if (BIO_get_offload_rx(s->rbio) && (*p == 0x7F)) { ++ RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_ERROR); ++ } ++ + /* + * The first record received by the server may be a V2ClientHello. + */ +@@ -393,6 +398,18 @@ int ssl3_get_record(SSL *s) + } + } + ++ if (BIO_get_offload_rx(s->rbio) && ++ RECORD_LAYER_get_rstate(&s->rlayer) == SSL_ST_READ_ERROR) { ++ i = rr[num_recs].length; ++ rret = ssl3_read_n(s, i, i, 1, 0, &n); ++ RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_HEADER); ++ if (rret <= 0) ++ return (rret); ++ SSLfatal(s, SSL_AD_BAD_RECORD_MAC, SSL_F_SSL3_GET_RECORD, ++ SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); ++ return -1; ++ } ++ + /* + * s->rlayer.rstate == SSL_ST_READ_BODY, get and decode the data. + * Calculate how much more data we need to read for the rest of the +@@ -495,7 +512,7 @@ int ssl3_get_record(SSL *s) + * If in encrypt-then-mac mode calculate mac from encrypted record. All + * the details below are public so no timing details can leak. + */ +- if (SSL_READ_ETM(s) && s->read_hash) { ++ if (SSL_READ_ETM(s) && s->read_hash && !BIO_get_offload_rx(s->rbio)) { + unsigned char *mac; + /* TODO(size_t): convert this to do size_t properly */ + imac_size = EVP_MD_CTX_size(s->read_hash); +@@ -526,7 +543,11 @@ int ssl3_get_record(SSL *s) + + first_rec_len = rr[0].length; + +- enc_err = s->method->ssl3_enc->enc(s, rr, num_recs, 0); ++ if (BIO_get_offload_rx(s->rbio)) { ++ enc_err = 1; ++ } else { ++ enc_err = s->method->ssl3_enc->enc(s, rr, num_recs, 0); ++ } + + /*- + * enc_err is: +@@ -576,6 +597,7 @@ int ssl3_get_record(SSL *s) + /* r->length is now the compressed data plus mac */ + if ((sess != NULL) && + (s->enc_read_ctx != NULL) && ++ !BIO_get_offload_rx(s->rbio) && + (!SSL_READ_ETM(s) && EVP_MD_CTX_md(s->read_hash) != NULL)) { + /* s->read_hash != NULL => mac_size != -1 */ + unsigned char *mac = NULL; +diff --git ssl/s3_msg.c ssl/s3_msg.c +index 42382547fb..a3d549604b 100644 +--- ssl/s3_msg.c ++++ ssl/s3_msg.c +@@ -8,6 +8,7 @@ + */ + + #include "ssl_locl.h" ++#include "ssl_ofld.h" + + int ssl3_do_change_cipher_spec(SSL *s) + { +@@ -33,6 +34,18 @@ int ssl3_do_change_cipher_spec(SSL *s) + if (!s->method->ssl3_enc->change_cipher_state(s, i)) + return 0; + ++#ifdef CHELSIO_TLS_OFFLOAD ++ if (!s->server) { ++ if (s->wbio) { ++ chssl_program_hwkey_context(s, SSL3_CC_READ, SSL_ST_CONNECT); ++ } ++ } else { ++ if (s->wbio) { ++ chssl_program_hwkey_context(s, SSL3_CC_READ, SSL_ST_ACCEPT); ++ } ++ } ++#endif ++ + return 1; + } + +diff --git ssl/ssl_ofld.c ssl/ssl_ofld.c +new file mode 100644 +index 0000000000..ba372e2d99 +--- /dev/null ++++ ssl/ssl_ofld.c +@@ -0,0 +1,413 @@ ++/* ++ * Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved. ++ * ++ * Licensed under the OpenSSL license (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 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "ssl_locl.h" ++#include "ssl_ofld.h" ++ ++#ifdef CHELSIO_TLS_OFFLOAD ++int CHSSL_EVP_Digest(const void *data, ++ void *md, unsigned long algorithm_mac) ++{ ++ unsigned char *temp = md; ++ int ret = 1, i; ++ ++ if (algorithm_mac == SSL_SHA1){ ++ SHA_CTX sha1ctx; ++ ++ SHA1_Init(&sha1ctx); ++ SHA1_Update(&sha1ctx, data, SHA_CBLOCK); ++ l2n(sha1ctx.h0, temp); ++ l2n(sha1ctx.h1, temp); ++ l2n(sha1ctx.h2, temp); ++ l2n(sha1ctx.h3, temp); ++ l2n(sha1ctx.h4, temp); ++ } else if (algorithm_mac == SSL_SHA256) { ++ SHA256_CTX sha256ctx; ++ SHA256_Init(&sha256ctx); ++ SHA256_Update(&sha256ctx, data, SHA256_CBLOCK); ++ ++ for (i = 0; i < SHA256_DIGEST_LENGTH / 4; i++) ++ l2n(sha256ctx.h[i], temp); ++ } else if (algorithm_mac == SSL_SHA384) { ++ SHA512_CTX sha384ctx; ++ ++ SHA384_Init(&sha384ctx); ++ SHA384_Update(&sha384ctx, data, SHA512_BLOCK); ++ ++ for (i = 0; i < SHA512_DIGEST_LENGTH / 8; i++) ++ l2n8(sha384ctx.h[i], temp); ++ } ++ ++ return ret; ++} ++ ++static int tls_ofld_enc_mac(SSL *s) ++{ ++ const EVP_CIPHER *p; ++ const SSL_CIPHER *c; ++ ++ c = s->s3->tmp.new_cipher; ++ p = s->s3->tmp.new_sym_enc; ++ ++ switch(c->algorithm_enc) { ++ case SSL_AES128GCM: ++ case SSL_AES256GCM: ++ return TLS_OFLD_TRUE; ++ ++ case SSL_AES128 : ++ case SSL_AES256 : ++ switch(EVP_CIPHER_mode(p)) { ++ case EVP_CIPH_CTR_MODE: ++ case EVP_CIPH_CBC_MODE: ++ break; ++ default: ++ return TLS_OFLD_FALSE; ++ } ++ break; ++ ++ case SSL_eNULL: ++ break; ++ ++ default: ++ return TLS_OFLD_FALSE; ++ } ++ ++ switch(c->algorithm_mac) { ++ case SSL_SHA1: ++ case SSL_SHA256: ++ case SSL_SHA384: ++ break; ++ ++ default: ++ /* Revert enc mode to non-offload */ ++ return TLS_OFLD_FALSE; ++ } ++ return TLS_OFLD_TRUE; ++} ++ ++static unsigned char get_auth_mode(SSL *s) ++{ ++ const SSL_CIPHER *c = s->s3->tmp.new_cipher; ++ ++ if(c==NULL) return CHSSL_SHA_NOP; ++ ++ switch(c->algorithm_mac) { ++ case SSL_SHA1: ++ return CHSSL_SHA1; ++ case SSL_SHA256: ++ return CHSSL_SHA256; ++ case SSL_SHA384: ++ return CHSSL_SHA512_384; ++ case SSL_AEAD: ++ return CHSSL_GHASH; ++ default: ++ return CHSSL_SHA_NOP; ++ } ++} ++ ++/* ++ * Cipher Mode expected by HW ++ */ ++static unsigned char get_cipher_mode(SSL *s) ++{ ++ const EVP_CIPHER *c = s->s3->tmp.new_sym_enc; ++ ++ switch(EVP_CIPHER_mode(c)) { ++ case EVP_CIPH_CBC_MODE: ++ return CHSSL_AES_CBC; ++ case EVP_CIPH_GCM_MODE: ++ return CHSSL_AES_GCM; ++ case EVP_CIPH_CTR_MODE: ++ return CHSSL_AES_CTR; ++ case EVP_CIPH_STREAM_CIPHER: ++ return CHSSL_CIPH_NOP; ++ default: ++ return CHSSL_CIPH_NOP; ++ } ++} ++ ++/* ++ * H/W requires Partial Hash of opad and ipad. This function create ++ * ipad, opad block using key and generates partial result ++ */ ++static void chssl_compute_ipad_opad(unsigned char *key, ++ unsigned char *ipad, ++ unsigned char *opad, ++ int k, unsigned long algorithm_mac) ++{ ++ int i, blksize; ++ char iblock[SHA512_BLOCK] = {0}; ++ char oblock[SHA512_BLOCK] = {0}; ++ ++ if (algorithm_mac == SSL_SHA384) ++ blksize = SHA512_CBLOCK; ++ else ++ blksize = SHA256_CBLOCK; ++ memset (iblock + k, 0x36, blksize - k); ++ memset (oblock + k, 0x5c, blksize - k); ++ for(i = 0; i < k; i++) { ++ iblock[i] = key[i] ^ 0x36; ++ oblock[i] = key[i] ^ 0x5c; ++ } ++ CHSSL_EVP_Digest(iblock, ipad, algorithm_mac); ++ CHSSL_EVP_Digest(oblock, opad, algorithm_mac); ++} ++ ++static void chssl_compute_cipher_key(unsigned char *key, ++ int key_len, ++ unsigned char *ghash) ++{ ++ int len,len1; ++ EVP_CIPHER_CTX *ctx; ++ unsigned char plaintext[GHASH_SIZE] = {0}; ++ ++ ctx = EVP_CIPHER_CTX_new(); ++ EVP_CIPHER_CTX_reset(ctx); ++ if(key_len == 16) ++ EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, NULL); ++ else ++ EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, NULL); ++ EVP_CIPHER_CTX_set_padding(ctx, 0); ++ EVP_EncryptUpdate(ctx, ghash, &len, plaintext, 16); ++ EVP_EncryptFinal_ex(ctx, ghash+len, &len1); ++ EVP_CIPHER_CTX_reset(ctx); ++ EVP_CIPHER_CTX_free(ctx); ++} ++ ++/* ++ * Create key Context for receive/transmit and program on HW ++ */ ++static int ssl_key_context(SSL *s, struct tls_key_context *kctx, int rw, int state) ++{ ++ const EVP_CIPHER *c; ++ unsigned int mac_key_size = 0, cipher_key_size, iv_size; ++ unsigned char *key; ++ unsigned char s_ipad_hash[MAX_MAC_KSZ]= {0x0}; /* blk sz for hashing */ ++ unsigned char s_opad_hash[MAX_MAC_KSZ]= {0x0}; /* blk sz for hashing */ ++ unsigned char c_ipad_hash[MAX_MAC_KSZ]= {0x0}; /* blk sz for hashing */ ++ unsigned char c_opad_hash[MAX_MAC_KSZ]= {0x0}; /* blk sz for hashing */ ++ ++ unsigned char s_mac_key[MAX_MAC_KSZ] = {0x0}; ++ unsigned char c_mac_key[MAX_MAC_KSZ] = {0x0}; ++ unsigned char s_key[MAX_CIPHER_KSZ] = {0x0}; ++ unsigned char c_key[MAX_CIPHER_KSZ] = {0x0}; ++ unsigned char s_iv[MAX_CIPHER_KSZ] = {0x0}; ++ unsigned char c_iv[MAX_CIPHER_KSZ] = {0x0}; ++ unsigned char ghash[GHASH_SIZE] = {0x0}; ++ int pad = 12; ++ int index = 0; ++ int ret = 0; ++ ++ if (!tls_ofld_enc_mac(s) || s->version < TLS1_VERSION) { ++ return ret; ++ } ++ ++ if (rw == SSL3_CC_READ && SSL_READ_ETM(s)) ++ return ret; ++ else if (rw == SSL3_CC_WRITE && SSL_WRITE_ETM(s)) ++ return ret; ++ ++ c = s->s3->tmp.new_sym_enc; ++ kctx->l_p_key = rw; ++ ++ if (s->new_session) ++ kctx->l_p_key |= F_KEY_CLR_LOC; ++ key = s->s3->tmp.key_block; ++ ++ mac_key_size = s->s3->tmp.new_mac_secret_size; ++ ++ kctx->mac_secret_size = mac_key_size; ++ ++ cipher_key_size = EVP_CIPHER_key_length(c); ++ kctx->cipher_secret_size = cipher_key_size; ++ ++ iv_size = (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE) ? ++ EVP_GCM_TLS_FIXED_IV_LEN: ++ EVP_CIPHER_iv_length(c); ++ kctx->iv_size = iv_size; ++ kctx->iv_ctrl = 1; ++ kctx->iv_algo = 0; ++ ++ if ((mac_key_size == SHA256_DIGEST_LENGTH) || ++ (mac_key_size == SHA384_DIGEST_LENGTH)) ++ pad = 0; ++ ++ if (mac_key_size) { ++ memcpy(c_mac_key, key, mac_key_size); ++ key += mac_key_size; ++ memcpy(s_mac_key, key, mac_key_size); ++ key += mac_key_size; ++ } ++ memcpy(c_key, key, cipher_key_size); ++ key += cipher_key_size; ++ memcpy(s_key, key, cipher_key_size); ++ key += cipher_key_size; ++ ++ memcpy(c_iv, key, iv_size); ++ key += iv_size; ++ memcpy(s_iv, key, iv_size); ++ ++ if ((EVP_CIPHER_mode(c) != EVP_CIPH_GCM_MODE)) { ++ /* IPAD/OPAD for SHA384/512 calculated over 128B block */ ++ chssl_compute_ipad_opad(c_mac_key, c_ipad_hash, ++ c_opad_hash, mac_key_size, ++ s->s3->tmp.new_cipher->algorithm_mac); ++ chssl_compute_ipad_opad(s_mac_key, s_ipad_hash, ++ s_opad_hash, mac_key_size, ++ s->s3->tmp.new_cipher->algorithm_mac); ++ } ++ ++ if (state == SSL_ST_ACCEPT) { ++ memcpy(kctx->tx.key, s_key, cipher_key_size); ++ memcpy(kctx->rx.key, c_key, cipher_key_size); ++ } else { ++ memcpy(kctx->tx.key, c_key, cipher_key_size); ++ memcpy(kctx->rx.key, s_key, cipher_key_size); ++ } ++ ++ if (mac_key_size == SHA384_DIGEST_LENGTH) mac_key_size = MAX_MAC_KSZ; ++ index = cipher_key_size; ++ if (mac_key_size) { ++ if (state == SSL_ST_ACCEPT) ++ memcpy(kctx->tx.key+index, s_ipad_hash, mac_key_size); ++ else ++ memcpy(kctx->tx.key+index, c_ipad_hash, mac_key_size); ++ ++ index += (mac_key_size + pad); ++ if (state == SSL_ST_ACCEPT) ++ memcpy(kctx->tx.key+index, s_opad_hash, mac_key_size); ++ else ++ memcpy(kctx->tx.key+index, c_opad_hash, mac_key_size); ++ ++ index += (mac_key_size + pad); ++ } else { ++ if (state == SSL_ST_ACCEPT) { ++ chssl_compute_cipher_key(s_key, cipher_key_size, ghash); ++ memcpy(kctx->tx.key+index, ghash, GHASH_SIZE); ++ } else { ++ chssl_compute_cipher_key(c_key, cipher_key_size, ghash); ++ memcpy(kctx->tx.key+index, ghash, GHASH_SIZE); ++ } ++ index += GHASH_SIZE; ++ } ++ kctx->tx_key_info_size = TLS_TX_HDR_SZ + index; ++ index = cipher_key_size; ++ if (mac_key_size) { ++ if (state == SSL_ST_ACCEPT) ++ memcpy(kctx->rx.key+index, c_ipad_hash, mac_key_size); ++ else ++ memcpy(kctx->rx.key+index, s_ipad_hash, mac_key_size); ++ ++ index += (mac_key_size + pad); ++ if (state == SSL_ST_ACCEPT) ++ memcpy(kctx->rx.key+index, c_opad_hash, mac_key_size); ++ else ++ memcpy(kctx->rx.key+index, s_opad_hash, mac_key_size); ++ ++ index += (mac_key_size + pad); ++ } else { ++ if (state == SSL_ST_ACCEPT) { ++ chssl_compute_cipher_key(c_key, cipher_key_size, ghash); ++ memcpy(kctx->rx.key+index, ghash, GHASH_SIZE); ++ } else { ++ chssl_compute_cipher_key(s_key, cipher_key_size, ghash); ++ memcpy(kctx->rx.key+index, ghash, GHASH_SIZE); ++ } ++ index += GHASH_SIZE; ++ } ++ ++ kctx->tx_key_info_size = TLS_RX_HDR_SZ + index; ++ ++ if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE) { ++ if (state == SSL_ST_ACCEPT) { ++ memcpy(kctx->tx.salt, s_iv, SALT_SIZE); ++ memcpy(kctx->rx.salt, c_iv, SALT_SIZE); ++ } else { ++ memcpy(kctx->tx.salt, c_iv, SALT_SIZE); ++ memcpy(kctx->rx.salt, s_iv, SALT_SIZE); ++ } ++ } ++ ++ kctx->proto_ver = s->version; ++ kctx->state.auth_mode = get_auth_mode(s); ++ kctx->state.enc_mode = get_cipher_mode(s); ++ ++ if (s->max_send_fragment) ++ kctx->frag_size = s->max_send_fragment; ++ else ++ kctx->frag_size = SSL3_RT_MAX_PLAIN_LENGTH; ++ ++ /* handle renegotiation here */ ++ if(!BIO_get_offload_tx(s->wbio)) ++ kctx->tx_seq_no = 0; ++ else ++ kctx->tx_seq_no = 1; ++ ++ if(!BIO_get_offload_rx(s->rbio)) ++ kctx->rx_seq_no = 0; ++ else ++ kctx->rx_seq_no = 1; ++ ++ if(EVP_CIPHER_mode(c) != EVP_CIPH_GCM_MODE) { ++ kctx->hmac_ctrl = 1; ++ } ++ ++ return 1; ++} ++ ++void chssl_program_hwkey_context(SSL *s, int rw, int state) ++{ ++ int ret = 0; ++ BIO *wbio; ++ BIO *rbio; ++ struct tls_key_context *key_context; ++ ++ wbio = s->wbio; ++ rbio = s->rbio; ++ if (!BIO_get_chofld_flag(rbio)) ++ return; ++ ++ key_context = (struct tls_key_context *) ++ OPENSSL_malloc(sizeof(struct tls_key_context)); ++ if (key_context == NULL) ++ return; ++ ++ memset(key_context, 0, sizeof(struct tls_key_context)); ++ if((ret = ssl_key_context(s, key_context, rw, state)) <=0) { ++ /* Clear quiesce after CCS receive */ ++ if (rw == KEY_WRITE_RX) ++ BIO_set_offload_clear_key(wbio); ++ goto end; ++ } ++ ++ /* flush outstanding BIO before key is programmed */ ++ statem_flush(s); ++ ret = BIO_set_offload_key(wbio, key_context); ++ if (ret) ++ goto end; ++ if (rw & KEY_WRITE_TX) { ++ /* XXX: wbio? */ ++ BIO_set_offload_tx_flag(rbio); ++ } else { ++ BIO_set_offload_rx_flag(rbio); ++ } ++end: ++ free(key_context); ++ return; ++} ++#endif +diff --git ssl/ssl_ofld.h ssl/ssl_ofld.h +new file mode 100644 +index 0000000000..6b153bef9b +--- /dev/null ++++ ssl/ssl_ofld.h +@@ -0,0 +1,141 @@ ++#ifndef _SSL_OFLD_H ++#define _SSL_OFLD_H ++ ++#ifdef CHELSIO_TLS_OFFLOAD ++void chssl_program_hwkey_context(SSL *s, int rw, int state); ++ ++#define MAX_MAC_KSZ 64 /*512 bits */ ++#define SHA512_BLOCK 128 /* Block size for 512 */ ++#define MAX_CIPHER_KSZ 32 /* 256 bits */ ++#define CIPHER_BLOCK_SZ 16 ++#define IV_SIZE (4+8) /*reserved 8 bytes */ ++#define SALT_SIZE 4 ++#define TLS_TX_HDR_SZ 16 ++#define TLS_RX_HDR_SZ 16 ++#define GHASH_SIZE 16 ++#define MAX_TLS_KSZ (2*MAX_MAC_KSZ + MAX_CIPHER_KSZ) ++ ++#ifdef __linux__ ++#define IOCTL_TLSOM_SET_TLS_CONTEXT 201 /* Program Key Context on HW */ ++#define IOCTL_TLSOM_GET_TLS_TOM 202 /* Query the TLS offload mode */ ++#define IOCTL_TLSOM_CLR_TLS_TOM 203 /* Clear the Key */ ++#define IOCTL_TLSOM_CLR_QUIES 204 /* Clear the Quiesec */ ++#else ++/* Set with 'struct tls_key_context'. */ ++#define TCP_TLSOM_SET_TLS_CONTEXT (TCP_VENDOR) ++ ++/* Get returns int of enabled (1) / disabled (0). */ ++#define TCP_TLSOM_GET_TLS_TOM (TCP_VENDOR + 1) ++ ++enum { ++ TLS_TOM_NONE = 0, ++ TLS_TOM_TXONLY, ++ TLS_TOM_BOTH ++}; ++ ++/* Set with no value. */ ++#define TCP_TLSOM_CLR_TLS_TOM (TCP_VENDOR + 2) ++ ++/* Set with no value. */ ++#define TCP_TLSOM_CLR_QUIES (TCP_VENDOR + 3) ++#endif ++ ++enum { ++ TLS_OFLD_FALSE = 0, ++ TLS_OFLD_TRUE, ++}; ++ ++/* Can accomodate 16, 11-15 are reserved */ ++enum { ++ CHSSL_SHA_NOP, ++ CHSSL_SHA1, ++ CHSSL_SHA224, ++ CHSSL_SHA256, ++ CHSSL_GHASH, ++ CHSSL_SHA512_224, ++ CHSSL_SHA512_256, ++ CHSSL_SHA512_384, ++ CHSSL_SHA512_512, ++ CHSSL_CBCMAC, ++ CHSSL_CMAC, ++}; ++ ++/* Can accomodate 16, 8-15 are reserved */ ++enum { ++ CHSSL_CIPH_NOP, ++ CHSSL_AES_CBC, ++ CHSSL_AES_GCM, ++ CHSSL_AES_CTR, ++ CHSSL_AES_GEN, ++ CHSSL_IPSEC_ESP, ++ CHSSL_AES_XTS, ++ CHSSL_AES_CCM, ++}; ++ ++#define KEY_WRITE_RX 0x1 /* Program Receive Key */ ++#define KEY_WRITE_TX 0x2 /* Program Transmit Key */ ++#define KEY_DELETE_RX 0x4 /* Delete Receive Key */ ++#define KEY_DELETE_TX 0x8 /* Delete Transmit Key */ ++ ++#define S_KEY_CLR_LOC 4 ++#define M_KEY_CLR_LOC 0xf ++#define V_KEY_CLR_LOC(x) ((x) << S_KEY_CLR_LOC) ++#define G_FW_WR_EQUIQ(s) (((x) >> S_KEY_CLR_LOC) & M_KEY_CLR_LOC) ++#define F_KEY_CLR_LOC V_KEY_CLR_LOC(1U) ++ ++#define S_KEY_GET_LOC 0 ++#define M_KEY_GET_LOC 0xf ++#define V_KEY_GET_LOC(x) ((x) << S_KEY_GET_LOC) ++#define G_KEY_GET_LOC(s) (((x) >> S_KEY_GET_LOC) & M_KEY_GET_LOC) ++ ++struct tls_ofld_state { ++ unsigned char enc_mode; ++ unsigned char mac_mode; ++ unsigned char key_loc; ++ unsigned char ofld_mode; ++ unsigned char auth_mode; ++ unsigned char resv[3]; ++}; ++ ++struct tls_tx_ctxt { ++ unsigned char salt[SALT_SIZE]; ++ unsigned char key[MAX_CIPHER_KSZ]; ++ unsigned char ipad[MAX_MAC_KSZ]; ++ unsigned char opad[MAX_MAC_KSZ]; ++}; ++ ++struct tls_rx_ctxt { ++ unsigned char salt[SALT_SIZE]; ++ unsigned char key[MAX_CIPHER_KSZ]; ++ unsigned char ipad[MAX_MAC_KSZ]; ++ unsigned char opad[MAX_MAC_KSZ]; ++}; ++ ++struct tls_key_context { ++ struct tls_tx_ctxt tx; ++ struct tls_rx_ctxt rx; ++ ++ unsigned char l_p_key; ++ unsigned char hmac_ctrl; ++ unsigned char mac_first; ++ unsigned char iv_size; ++ unsigned char iv_ctrl; ++ unsigned char iv_algo; ++ unsigned char tx_seq_no; ++ unsigned char rx_seq_no; ++ ++ struct tls_ofld_state state; ++ ++ unsigned int tx_key_info_size; ++ unsigned int rx_key_info_size; ++ unsigned int frag_size; ++ unsigned int mac_secret_size; ++ unsigned int cipher_secret_size; ++ int proto_ver; ++ unsigned int sock_fd; ++ unsigned short dtls_epoch; ++ unsigned short rsv; ++}; ++#endif ++ ++#endif /* ssl_ofld.h */ +diff --git ssl/statem/statem_srvr.c ssl/statem/statem_srvr.c +index 7d0e9d0ba8..4bb38211f9 100644 +--- ssl/statem/statem_srvr.c ++++ ssl/statem/statem_srvr.c +@@ -650,6 +650,10 @@ WRITE_TRAN ossl_statem_server_write_transition(SSL *s) + + case TLS_ST_SW_SESSION_TICKET: + st->hand_state = TLS_ST_SW_CHANGE; ++#ifdef CHELSIO_TLS_OFFLOAD ++ if (BIO_get_chofld_flag(s->rbio)) ++ statem_flush(s); ++#endif + return WRITE_TRAN_CONTINUE; + + case TLS_ST_SW_CHANGE: +diff --git ssl/t1_enc.c ssl/t1_enc.c +index 2db913fb06..d7c90873af 100644 +--- ssl/t1_enc.c ++++ ssl/t1_enc.c +@@ -10,6 +10,7 @@ + + #include + #include "ssl_locl.h" ++#include "ssl_ofld.h" + #include + #include + #include +@@ -98,6 +99,7 @@ int tls1_change_cipher_state(SSL *s, int which) + EVP_PKEY *mac_key; + size_t n, i, j, k, cl; + int reuse_dd = 0; ++ BIO *wbio; + + c = s->s3->tmp.new_sym_enc; + m = s->s3->tmp.new_hash; +@@ -318,6 +320,22 @@ int tls1_change_cipher_state(SSL *s, int which) + } + s->statem.enc_write_state = ENC_WRITE_STATE_VALID; + ++#ifdef CHELSIO_TLS_OFFLOAD ++ wbio = s->wbio; ++ if (!wbio) ++ goto skip_offload; ++ ++ if (which == SSL3_CHANGE_CIPHER_SERVER_WRITE) { ++ chssl_program_hwkey_context(s, SSL3_CC_WRITE, SSL_ST_ACCEPT); ++ //statem_flush(s); ++ } else if (which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) { ++ chssl_program_hwkey_context(s, SSL3_CC_WRITE, SSL_ST_CONNECT); ++ //statem_flush(s); ++ } ++ ++skip_offload: ++#endif ++ + #ifdef SSL_DEBUG + printf("which = %04X\nkey=", which); + { Index: security/openssl-chelsio/files/patch-config =================================================================== --- /dev/null +++ security/openssl-chelsio/files/patch-config @@ -0,0 +1,19 @@ +--- config.orig 2018-01-13 13:57:15 UTC ++++ config +@@ -694,14 +694,8 @@ case "$GUESSOS" in + ia64-*-*bsd*) OUT="BSD-ia64" ;; + x86_64-*-dragonfly*) OUT="BSD-x86_64" ;; + amd64-*-*bsd*) OUT="BSD-x86_64" ;; +- *86*-*-*bsd*) # mimic ld behaviour when it's looking for libc... +- if [ -L /usr/lib/libc.so ]; then # [Free|Net]BSD +- libc=/usr/lib/libc.so +- else # OpenBSD +- # ld searches for highest libc.so.* and so do we +- libc=`(ls /usr/lib/libc.so.* /lib/libc.so.* | tail -1) 2>/dev/null` +- fi +- case "`(file -L $libc) 2>/dev/null`" in ++ *86*-*-*bsd*) ++ case "`(file -L /bin/sh) 2>/dev/null`" in + *ELF*) OUT="BSD-x86-elf" ;; + *) OUT="BSD-x86"; options="$options no-sse2" ;; + esac ;; Index: security/openssl-chelsio/files/pkg-message.in =================================================================== --- /dev/null +++ security/openssl-chelsio/files/pkg-message.in @@ -0,0 +1,4 @@ + +Copy %%PREFIX%%/openssl-chelsio/openssl.cnf.sample to +%%PREFIX%%/openssl-chelsio/openssl.cnf and edit it to fit your needs. + Index: security/openssl-chelsio/pkg-descr =================================================================== --- /dev/null +++ security/openssl-chelsio/pkg-descr @@ -0,0 +1,19 @@ +The OpenSSL Project is a collaborative effort to develop a robust, +commercial-grade, full-featured, and Open Source toolkit implementing +the Secure Sockets Layer (SSL v3) and Transport Layer Security (TLS v1, +v1.1, v1.2, v1.3) protocols with full-strength cryptography world-wide. +The project is managed by a worldwide community of volunteers that use +the Internet to communicate, plan, and develop the OpenSSL tookit +and its related documentation. + +OpenSSL is based on the excellent SSLeay library developed by Eric +A. Young and Tim J. Hudson. The OpenSSL toolkit is licensed under +an Apache-style licence, which basically means that you are free +to get and use it for commercial and non-commercial purposes subject +to some simple license conditions. + +This version of OpenSSL includes additional patches to support the +use of TLS offload for offloaded TCP connections on Chelsio T6 +network adapters. + +WWW: https://www.openssl.org/ Index: security/openssl-chelsio/pkg-plist =================================================================== --- /dev/null +++ security/openssl-chelsio/pkg-plist @@ -0,0 +1,8 @@ +openssl-chelsio/lib/engines-1.1/capi.so +openssl-chelsio/lib/engines-1.1/padlock.so +openssl-chelsio/lib/libcrypto.so.%%SHLIBVER%% +openssl-chelsio/lib/libssl.so.%%SHLIBVER%% +@sample %%OPENSSLDIR%%/openssl.cnf.dist %%OPENSSLDIR%%/openssl.cnf +@sample %%OPENSSLDIR%%/ct_log_list.cnf.dist %%OPENSSLDIR%%/ct_log_list.cnf +@dir %%OPENSSLDIR%%/private +@dir %%OPENSSLDIR%%/certs Index: security/openssl-chelsio/version.mk =================================================================== --- /dev/null +++ security/openssl-chelsio/version.mk @@ -0,0 +1,2 @@ +# Match FreeBSD 12's base version +OPENSSL_SHLIBVER?= 111