Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F115347360
D33007.id98559.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
15 KB
Referenced Files
None
Subscribers
None
D33007.id98559.diff
View Options
Index: sys/kern/uipc_ktls.c
===================================================================
--- sys/kern/uipc_ktls.c
+++ sys/kern/uipc_ktls.c
@@ -1193,11 +1193,6 @@
if (en->cipher_algorithm == CRYPTO_AES_CBC && !ktls_cbc_enable)
return (ENOTSUP);
- /* TLS 1.3 is not yet supported. */
- if (en->tls_vmajor == TLS_MAJOR_VER_ONE &&
- en->tls_vminor == TLS_MINOR_VER_THREE)
- return (ENOTSUP);
-
error = ktls_create_session(so, en, &tls);
if (error)
return (error);
@@ -1922,6 +1917,8 @@
struct mbuf *control, *data, *m;
uint64_t seqno;
int error, remain, tls_len, trail_len;
+ bool tls13;
+ uint8_t vminor, record_type;
hdr = (struct tls_record_layer *)tls_header;
sb = &so->so_rcv;
@@ -1932,6 +1929,11 @@
tls = sb->sb_tls_info;
MPASS(tls != NULL);
+ tls13 = (tls->params.tls_vminor == TLS_MINOR_VER_THREE);
+ if (tls13)
+ vminor = TLS_MINOR_VER_TWO;
+ else
+ vminor = tls->params.tls_vminor;
for (;;) {
/* Is there enough queued for a TLS header? */
if (sb->sb_tlscc < tls->params.tls_hlen)
@@ -1941,7 +1943,9 @@
tls_len = sizeof(*hdr) + ntohs(hdr->tls_length);
if (hdr->tls_vmajor != tls->params.tls_vmajor ||
- hdr->tls_vminor != tls->params.tls_vminor)
+ hdr->tls_vminor != vminor)
+ error = EINVAL;
+ else if (tls13 && hdr->tls_type != TLS_RLTYPE_APP)
error = EINVAL;
else if (tls_len < tls->params.tls_hlen || tls_len >
tls->params.tls_hlen + TLS_MAX_MSG_SIZE_V10_2 +
@@ -1983,7 +1987,8 @@
SBCHECK(sb);
SOCKBUF_UNLOCK(sb);
- error = tls->sw_decrypt(tls, hdr, data, seqno, &trail_len);
+ error = tls->sw_decrypt(tls, hdr, data, seqno, &trail_len,
+ &record_type);
if (error) {
counter_u64_add(ktls_offload_failed_crypto, 1);
@@ -2016,7 +2021,7 @@
}
/* Allocate the control mbuf. */
- tgr.tls_type = hdr->tls_type;
+ tgr.tls_type = record_type;
tgr.tls_vmajor = hdr->tls_vmajor;
tgr.tls_vminor = hdr->tls_vminor;
tgr.tls_length = htobe16(tls_len - tls->params.tls_hlen -
Index: sys/opencrypto/ktls_ocf.c
===================================================================
--- sys/opencrypto/ktls_ocf.c
+++ sys/opencrypto/ktls_ocf.c
@@ -106,11 +106,21 @@
CTLFLAG_RD, &ocf_tls12_chacha20_encrypts,
"Total number of OCF TLS 1.2 Chacha20-Poly1305 encryption operations");
+static COUNTER_U64_DEFINE_EARLY(ocf_tls13_gcm_decrypts);
+SYSCTL_COUNTER_U64(_kern_ipc_tls_stats_ocf, OID_AUTO, tls13_gcm_decrypts,
+ CTLFLAG_RD, &ocf_tls13_gcm_decrypts,
+ "Total number of OCF TLS 1.3 GCM decryption operations");
+
static COUNTER_U64_DEFINE_EARLY(ocf_tls13_gcm_encrypts);
SYSCTL_COUNTER_U64(_kern_ipc_tls_stats_ocf, OID_AUTO, tls13_gcm_encrypts,
CTLFLAG_RD, &ocf_tls13_gcm_encrypts,
"Total number of OCF TLS 1.3 GCM encryption operations");
+static COUNTER_U64_DEFINE_EARLY(ocf_tls13_chacha20_decrypts);
+SYSCTL_COUNTER_U64(_kern_ipc_tls_stats_ocf, OID_AUTO, tls13_chacha20_decrypts,
+ CTLFLAG_RD, &ocf_tls13_chacha20_decrypts,
+ "Total number of OCF TLS 1.3 Chacha20-Poly1305 decryption operations");
+
static COUNTER_U64_DEFINE_EARLY(ocf_tls13_chacha20_encrypts);
SYSCTL_COUNTER_U64(_kern_ipc_tls_stats_ocf, OID_AUTO, tls13_chacha20_encrypts,
CTLFLAG_RD, &ocf_tls13_chacha20_encrypts,
@@ -462,7 +472,7 @@
static int
ktls_ocf_tls12_aead_decrypt(struct ktls_session *tls,
const struct tls_record_layer *hdr, struct mbuf *m, uint64_t seqno,
- int *trailer_len)
+ int *trailer_len, uint8_t *record_type)
{
struct tls_aead_data ad;
struct cryptop crp;
@@ -519,6 +529,7 @@
crypto_destroyreq(&crp);
*trailer_len = tls->params.tls_tlen;
+ *record_type = hdr->tls_type;
return (error);
}
@@ -600,6 +611,95 @@
return (error);
}
+static int
+ktls_ocf_tls13_aead_decrypt(struct ktls_session *tls,
+ const struct tls_record_layer *hdr, struct mbuf *m, uint64_t seqno,
+ int *trailer_len, uint8_t *record_typep)
+{
+ struct tls_aead_data_13 ad;
+ struct cryptop crp;
+ struct ktls_ocf_session *os;
+ char *cp;
+ int error;
+ u_int tag_len, offset, last_offset, m_len;
+ uint8_t record_type;
+
+ os = tls->ocf_session;
+
+ if (tls->params.cipher_algorithm == CRYPTO_AES_NIST_GCM_16)
+ tag_len = AES_GMAC_HASH_LEN;
+ else
+ tag_len = POLY1305_HASH_LEN;
+
+ /* Payload must contain at least one byte for the record type. */
+ if (ntohs(hdr->tls_length) < tag_len + 1)
+ return (EBADMSG);
+
+ crypto_initreq(&crp, os->sid);
+
+ /* Setup the nonce. */
+ memcpy(crp.crp_iv, tls->params.iv, tls->params.iv_len);
+ *(uint64_t *)(crp.crp_iv + 4) ^= htobe64(seqno);
+
+ /* Setup the AAD. */
+ ad.type = hdr->tls_type;
+ ad.tls_vmajor = hdr->tls_vmajor;
+ ad.tls_vminor = hdr->tls_vminor;
+ ad.tls_length = hdr->tls_length;
+ crp.crp_aad = &ad;
+ crp.crp_aad_length = sizeof(ad);
+
+ crp.crp_payload_start = tls->params.tls_hlen;
+ crp.crp_payload_length = ntohs(hdr->tls_length) - tag_len;
+ crp.crp_digest_start = crp.crp_payload_start + crp.crp_payload_length;
+
+ crp.crp_op = CRYPTO_OP_DECRYPT | CRYPTO_OP_VERIFY_DIGEST;
+ crp.crp_flags = CRYPTO_F_CBIMM | CRYPTO_F_IV_SEPARATE;
+ crypto_use_mbuf(&crp, m);
+
+ if (tls->params.cipher_algorithm == CRYPTO_AES_NIST_GCM_16)
+ counter_u64_add(ocf_tls13_gcm_decrypts, 1);
+ else
+ counter_u64_add(ocf_tls13_chacha20_decrypts, 1);
+ error = ktls_ocf_dispatch(os, &crp);
+
+ crypto_destroyreq(&crp);
+
+ /*
+ * Determine the length of the trailing zero padding and find
+ * the real record type in the byte before the padding.
+ *
+ * Walking the mbuf chain backwards is clumsy, so another
+ * option would be to scan forwards remembering the last
+ * non-zero byte before the trailer. However, it would be
+ * expensive to scan the entire record. Instead, find the
+ * last non-zero byte of each mbuf in the chain keeping track
+ * of the relative offset of that nonzero byte.
+ */
+ last_offset = 0;
+ offset = 0;
+ for (; m != NULL && offset < crp.crp_digest_start;
+ offset += m->m_len, m = m->m_next) {
+ /* Don't look for padding in the tag. */
+ m_len = min(crp.crp_digest_start - offset, m->m_len);
+ cp = mtod(m, char *);
+
+ /* Find last non-zero byte in this mbuf. */
+ while (m_len > 0 && cp[m_len - 1] == 0)
+ m_len--;
+ if (m_len > 0) {
+ record_type = cp[m_len - 1];
+ last_offset = offset + m_len;
+ }
+ }
+ if (last_offset < tls->params.tls_hlen)
+ return (EBADMSG);
+
+ *record_typep = record_type;
+ *trailer_len = crp.crp_digest_start + tag_len - last_offset + 1;
+ return (error);
+}
+
void
ktls_ocf_free(struct ktls_session *tls)
{
@@ -639,11 +739,6 @@
tls->params.tls_vminor > TLS_MINOR_VER_THREE)
return (EPROTONOSUPPORT);
- /* TLS 1.3 is not yet supported for receive. */
- if (direction == KTLS_RX &&
- tls->params.tls_vminor == TLS_MINOR_VER_THREE)
- return (EPROTONOSUPPORT);
-
csp.csp_flags |= CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD;
csp.csp_mode = CSP_MODE_AEAD;
csp.csp_cipher_alg = CRYPTO_AES_NIST_GCM_16;
@@ -711,11 +806,6 @@
tls->params.tls_vminor > TLS_MINOR_VER_THREE)
return (EPROTONOSUPPORT);
- /* TLS 1.3 is not yet supported for receive. */
- if (direction == KTLS_RX &&
- tls->params.tls_vminor == TLS_MINOR_VER_THREE)
- return (EPROTONOSUPPORT);
-
csp.csp_flags |= CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD;
csp.csp_mode = CSP_MODE_AEAD;
csp.csp_cipher_alg = CRYPTO_CHACHA20_POLY1305;
@@ -759,7 +849,10 @@
else
tls->sw_encrypt = ktls_ocf_tls12_aead_encrypt;
} else {
- tls->sw_decrypt = ktls_ocf_tls12_aead_decrypt;
+ if (tls->params.tls_vminor == TLS_MINOR_VER_THREE)
+ tls->sw_decrypt = ktls_ocf_tls13_aead_decrypt;
+ else
+ tls->sw_decrypt = ktls_ocf_tls12_aead_decrypt;
}
} else {
tls->sw_encrypt = ktls_ocf_tls_cbc_encrypt;
Index: sys/sys/ktls.h
===================================================================
--- sys/sys/ktls.h
+++ sys/sys/ktls.h
@@ -182,7 +182,7 @@
struct iovec *outiov, int outiovcnt);
int (*sw_decrypt)(struct ktls_session *tls,
const struct tls_record_layer *hdr, struct mbuf *m,
- uint64_t seqno, int *trailer_len);
+ uint64_t seqno, int *trailer_len, uint8_t *record_type);
};
struct ktls_ocf_session *ocf_session;
struct m_snd_tag *snd_tag;
Index: tests/sys/kern/ktls_test.c
===================================================================
--- tests/sys/kern/ktls_test.c
+++ tests/sys/kern/ktls_test.c
@@ -816,26 +816,74 @@
return (record_len);
}
+static size_t
+encrypt_tls_13_aead(struct tls_enable *en, uint8_t record_type, uint64_t seqno,
+ const void *src, size_t len, void *dst, size_t padding)
+{
+ struct tls_record_layer *hdr;
+ struct tls_aead_data_13 aad;
+ char nonce[12];
+ char *buf;
+ size_t hdr_len, mac_len, record_len;
+
+ hdr = dst;
+
+ hdr_len = tls_header_len(en);
+ mac_len = tls_mac_len(en);
+ record_len = hdr_len + len + 1 + padding + mac_len;
+
+ hdr->tls_type = TLS_RLTYPE_APP;
+ hdr->tls_vmajor = TLS_MAJOR_VER_ONE;
+ hdr->tls_vminor = TLS_MINOR_VER_TWO;
+ hdr->tls_length = htons(record_len - sizeof(*hdr));
+
+ tls_13_aad(en, hdr, seqno, &aad);
+ tls_13_nonce(en, seqno, nonce);
+
+ /*
+ * Have to use a temporary buffer for the input so that the record
+ * type can be appended.
+ */
+ buf = malloc(len + 1 + padding);
+ memcpy(buf, src, len);
+ buf[len] = record_type;
+ memset(buf + len + 1, 0, padding);
+
+ ATF_REQUIRE(aead_encrypt(tls_EVP_CIPHER(en), en->cipher_key, nonce,
+ &aad, sizeof(aad), buf, (char *)dst + hdr_len, len + 1 + padding,
+ (char *)dst + hdr_len + len + 1 + padding, mac_len));
+
+ free(buf);
+
+ return (record_len);
+}
+
static size_t
encrypt_tls_aead(struct tls_enable *en, uint8_t record_type, uint64_t seqno,
- const void *src, size_t len, void *dst, size_t avail)
+ const void *src, size_t len, void *dst, size_t avail, size_t padding)
{
size_t record_len;
- record_len = tls_header_len(en) + len + tls_trailer_len(en);
+ record_len = tls_header_len(en) + len + padding + tls_trailer_len(en);
ATF_REQUIRE(record_len <= avail);
- ATF_REQUIRE(encrypt_tls_12_aead(en, record_type, seqno, src, len,
- dst) == record_len);
+ if (en->tls_vminor == TLS_MINOR_VER_TWO) {
+ ATF_REQUIRE(padding == 0);
+ ATF_REQUIRE(encrypt_tls_12_aead(en, record_type, seqno, src,
+ len, dst) == record_len);
+ } else
+ ATF_REQUIRE(encrypt_tls_13_aead(en, record_type, seqno, src,
+ len, dst, padding) == record_len);
return (record_len);
}
static size_t
encrypt_tls_record(struct tls_enable *en, uint8_t record_type, uint64_t seqno,
- const void *src, size_t len, void *dst, size_t avail)
+ const void *src, size_t len, void *dst, size_t avail, size_t padding)
{
- return (encrypt_tls_aead(en, record_type, seqno, src, len, dst, avail));
+ return (encrypt_tls_aead(en, record_type, seqno, src, len, dst, avail,
+ padding));
}
static void
@@ -1121,14 +1169,19 @@
tgr = (struct tls_get_record *)CMSG_DATA(cmsg);
ATF_REQUIRE(tgr->tls_type == record_type);
ATF_REQUIRE(tgr->tls_vmajor == en->tls_vmajor);
- ATF_REQUIRE(tgr->tls_vminor == en->tls_vminor);
+ /* XXX: Not sure if this is what OpenSSL expects? */
+ if (en->tls_vminor == TLS_MINOR_VER_THREE)
+ ATF_REQUIRE(tgr->tls_vminor == TLS_MINOR_VER_TWO);
+ else
+ ATF_REQUIRE(tgr->tls_vminor == en->tls_vminor);
ATF_REQUIRE(tgr->tls_length == htons(rv));
return (rv);
}
static void
-test_ktls_receive_app_data(struct tls_enable *en, uint64_t seqno, size_t len)
+test_ktls_receive_app_data(struct tls_enable *en, uint64_t seqno, size_t len,
+ size_t padding)
{
struct kevent ev;
char *plaintext, *received, *outbuf;
@@ -1169,11 +1222,11 @@
if (outbuf_len == 0) {
ATF_REQUIRE(written < len);
todo = len - written;
- if (todo > TLS_MAX_MSG_SIZE_V10_2)
- todo = TLS_MAX_MSG_SIZE_V10_2;
+ if (todo > TLS_MAX_MSG_SIZE_V10_2 - padding)
+ todo = TLS_MAX_MSG_SIZE_V10_2 - padding;
outbuf_len = encrypt_tls_record(en,
TLS_RLTYPE_APP, seqno, plaintext + written,
- todo, outbuf, outbuf_cap);
+ todo, outbuf, outbuf_cap, padding);
outbuf_sent = 0;
written += todo;
seqno++;
@@ -1229,14 +1282,6 @@
M(aes256_cbc_1_0_sha1, CRYPTO_AES_CBC, 256 / 8, \
CRYPTO_SHA1_HMAC)
-#define TLS_12_TESTS(M) \
- M(aes128_gcm_1_2, CRYPTO_AES_NIST_GCM_16, 128 / 8, 0, \
- TLS_MINOR_VER_TWO) \
- M(aes256_gcm_1_2, CRYPTO_AES_NIST_GCM_16, 256 / 8, 0, \
- TLS_MINOR_VER_TWO) \
- M(chacha20_poly1305_1_2, CRYPTO_CHACHA20_POLY1305, 256 / 8, 0, \
- TLS_MINOR_VER_TWO)
-
#define TLS_13_TESTS(M) \
M(aes128_gcm_1_3, CRYPTO_AES_NIST_GCM_16, 128 / 8, 0, \
TLS_MINOR_VER_THREE) \
@@ -1528,7 +1573,7 @@
INVALID_CIPHER_SUITES(GEN_INVALID_TRANSMIT_TEST);
#define GEN_RECEIVE_APP_DATA_TEST(cipher_name, cipher_alg, key_size, \
- auth_alg, minor, name, len) \
+ auth_alg, minor, name, len, padding) \
ATF_TC_WITHOUT_HEAD(ktls_receive_##cipher_name##_##name); \
ATF_TC_BODY(ktls_receive_##cipher_name##_##name, tc) \
{ \
@@ -1539,7 +1584,7 @@
seqno = random(); \
build_tls_enable(cipher_alg, key_size, auth_alg, minor, seqno, \
&en); \
- test_ktls_receive_app_data(&en, seqno, len); \
+ test_ktls_receive_app_data(&en, seqno, len, padding); \
free_tls_enable(&en); \
}
@@ -1550,9 +1595,9 @@
#define GEN_RECEIVE_TESTS(cipher_name, cipher_alg, key_size, auth_alg, \
minor) \
GEN_RECEIVE_APP_DATA_TEST(cipher_name, cipher_alg, key_size, \
- auth_alg, minor, short, 64) \
+ auth_alg, minor, short, 64, 0) \
GEN_RECEIVE_APP_DATA_TEST(cipher_name, cipher_alg, key_size, \
- auth_alg, minor, long, 64 * 1024)
+ auth_alg, minor, long, 64 * 1024, 0)
#define ADD_RECEIVE_TESTS(cipher_name, cipher_alg, key_size, auth_alg, \
minor) \
@@ -1573,7 +1618,28 @@
* Note that receive is currently only supported for TLS 1.2 AEAD
* cipher suites.
*/
-TLS_12_TESTS(GEN_RECEIVE_TESTS);
+AES_GCM_TESTS(GEN_RECEIVE_TESTS);
+CHACHA20_TESTS(GEN_RECEIVE_TESTS);
+
+#define GEN_PADDING_RECEIVE_TESTS(cipher_name, cipher_alg, key_size, \
+ auth_alg, minor) \
+ GEN_RECEIVE_APP_DATA_TEST(cipher_name, cipher_alg, key_size, \
+ auth_alg, minor, short_padded, 64, 16) \
+ GEN_RECEIVE_APP_DATA_TEST(cipher_name, cipher_alg, key_size, \
+ auth_alg, minor, long_padded, 64 * 1024, 15)
+
+#define ADD_PADDING_RECEIVE_TESTS(cipher_name, cipher_alg, key_size, \
+ auth_alg, minor) \
+ ADD_RECEIVE_APP_DATA_TEST(cipher_name, cipher_alg, key_size, \
+ auth_alg, minor, short_padded) \
+ ADD_RECEIVE_APP_DATA_TEST(cipher_name, cipher_alg, key_size, \
+ auth_alg, minor, long_padded)
+
+/*
+ * For TLS 1.3 cipher suites, run two additional receive tests which
+ * use add padding to each record.
+ */
+TLS_13_TESTS(GEN_PADDING_RECEIVE_TESTS);
static void
test_ktls_invalid_receive_cipher_suite(struct tls_enable *en)
@@ -1584,12 +1650,7 @@
ATF_REQUIRE(setsockopt(sockets[1], IPPROTO_TCP, TCP_RXTLS_ENABLE, en,
sizeof(*en)) == -1);
-
- /*
- * XXX: TLS 1.3 fails with ENOTSUP before checking for invalid
- * ciphers.
- */
- ATF_REQUIRE(errno == EINVAL || errno == ENOTSUP);
+ ATF_REQUIRE(errno == EINVAL);
ATF_REQUIRE(close(sockets[1]) == 0);
ATF_REQUIRE(close(sockets[0]) == 0);
@@ -1629,7 +1690,7 @@
ATF_REQUIRE(setsockopt(sockets[1], IPPROTO_TCP, TCP_RXTLS_ENABLE, en,
sizeof(*en)) == -1);
- ATF_REQUIRE(errno == EPROTONOSUPPORT || errno == ENOTSUP);
+ ATF_REQUIRE(errno == EPROTONOSUPPORT);
ATF_REQUIRE(close(sockets[1]) == 0);
ATF_REQUIRE(close(sockets[0]) == 0);
@@ -1660,7 +1721,6 @@
* rejected.
*/
AES_CBC_TESTS(GEN_UNSUPPORTED_RECEIVE_TEST);
-TLS_13_TESTS(GEN_UNSUPPORTED_RECEIVE_TEST);
ATF_TP_ADD_TCS(tp)
{
@@ -1674,8 +1734,9 @@
/* Receive tests */
AES_CBC_TESTS(ADD_UNSUPPORTED_RECEIVE_TEST);
- TLS_12_TESTS(ADD_RECEIVE_TESTS);
- TLS_13_TESTS(ADD_UNSUPPORTED_RECEIVE_TEST);
+ AES_GCM_TESTS(ADD_RECEIVE_TESTS);
+ CHACHA20_TESTS(ADD_RECEIVE_TESTS);
+ TLS_13_TESTS(ADD_PADDING_RECEIVE_TESTS);
INVALID_CIPHER_SUITES(ADD_INVALID_RECEIVE_TEST);
return (atf_no_error());
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Apr 23, 9:03 PM (3 h, 33 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17719179
Default Alt Text
D33007.id98559.diff (15 KB)
Attached To
Mode
D33007: ktls: Support for TLS 1.3 receive offload.
Attached
Detach File
Event Timeline
Log In to Comment