Page MenuHomeFreeBSD

D37370.diff
No OneTemporary

D37370.diff

diff --git a/sys/kern/uipc_ktls.c b/sys/kern/uipc_ktls.c
--- a/sys/kern/uipc_ktls.c
+++ b/sys/kern/uipc_ktls.c
@@ -149,7 +149,7 @@
static bool ktls_cbc_enable = true;
SYSCTL_BOOL(_kern_ipc_tls, OID_AUTO, cbc_enable, CTLFLAG_RWTUN,
&ktls_cbc_enable, 1,
- "Enable Support of AES-CBC crypto for kernel TLS");
+ "Enable support of AES-CBC crypto for kernel TLS");
static bool ktls_sw_buffer_cache = true;
SYSCTL_BOOL(_kern_ipc_tls, OID_AUTO, sw_buffer_cache, CTLFLAG_RDTUN,
@@ -2444,8 +2444,10 @@
sb->sb_ccc -= tls_len;
sb->sb_tlsdcc = 0;
+ if (error != EMSGSIZE)
+ error = EBADMSG;
CURVNET_SET(so->so_vnet);
- so->so_error = EBADMSG;
+ so->so_error = error;
sorwakeup_locked(so);
CURVNET_RESTORE();
diff --git a/sys/opencrypto/ktls_ocf.c b/sys/opencrypto/ktls_ocf.c
--- a/sys/opencrypto/ktls_ocf.c
+++ b/sys/opencrypto/ktls_ocf.c
@@ -101,6 +101,11 @@
CTLFLAG_RD, &ocf_tls10_cbc_encrypts,
"Total number of OCF TLS 1.0 CBC encryption operations");
+static COUNTER_U64_DEFINE_EARLY(ocf_tls11_cbc_decrypts);
+SYSCTL_COUNTER_U64(_kern_ipc_tls_stats_ocf, OID_AUTO, tls11_cbc_decrypts,
+ CTLFLAG_RD, &ocf_tls11_cbc_decrypts,
+ "Total number of OCF TLS 1.1/1.2 CBC decryption operations");
+
static COUNTER_U64_DEFINE_EARLY(ocf_tls11_cbc_encrypts);
SYSCTL_COUNTER_U64(_kern_ipc_tls_stats_ocf, OID_AUTO, tls11_cbc_encrypts,
CTLFLAG_RD, &ocf_tls11_cbc_encrypts,
@@ -416,8 +421,129 @@
return (error);
}
+static int
+check_padding(void *arg, void *data, u_int len)
+{
+ uint8_t pad = *(uint8_t *)arg;
+ const char *cp = data;
+
+ while (len > 0) {
+ if (*cp != pad)
+ return (EBADMSG);
+ cp++;
+ len--;
+ }
+ return (0);
+}
+
+static int
+ktls_ocf_tls_cbc_decrypt(struct ktls_session *tls,
+ const struct tls_record_layer *hdr, struct mbuf *m, uint64_t seqno,
+ int *trailer_len)
+{
+ struct tls_mac_data ad;
+ struct cryptop crp;
+ struct uio uio;
+ struct ktls_ocf_session *os;
+ struct iovec *iov;
+ struct mbuf *n;
+ u_int iovcnt;
+ int i, error, skip;
+ uint16_t tls_len, tls_comp_len;
+ uint8_t pad;
+
+ os = tls->ocf_session;
+
+ /*
+ * Ensure record is a multiple of the cipher block size and
+ * contains at least an explicit IV, MAC, and at least one
+ * padding byte.
+ */
+ tls_len = ntohs(hdr->tls_length);
+ if (tls_len % AES_BLOCK_LEN != 0 ||
+ tls_len < AES_BLOCK_LEN + roundup2(os->mac_len + 1, AES_BLOCK_LEN))
+ return (EMSGSIZE);
+
+ /* First, decrypt the record. */
+ crypto_initreq(&crp, os->sid);
+ crp.crp_iv_start = sizeof(*hdr);
+ crp.crp_payload_start = tls->params.tls_hlen;
+ crp.crp_payload_length = tls_len - AES_BLOCK_LEN;
+ crypto_use_mbuf(&crp, m);
+ crp.crp_op = CRYPTO_OP_DECRYPT;
+ crp.crp_flags = CRYPTO_F_CBIMM;
+
+ counter_u64_add(ocf_tls11_cbc_decrypts, 1);
+
+ error = ktls_ocf_dispatch(os, &crp);
+ crypto_destroyreq(&crp);
+ if (error)
+ return (error);
+
+ /* Verify the padding. */
+ m_copydata(m, sizeof(*hdr) + tls_len - 1, 1, &pad);
+ *trailer_len = os->mac_len + pad + 1;
+ if (AES_BLOCK_LEN + *trailer_len > tls_len)
+ return (EBADMSG);
+ error = m_apply(m, sizeof(*hdr) + tls_len - (pad + 1), pad + 1,
+ check_padding, &pad);
+ if (error)
+ return (error);
+
+ /* Verify the MAC. */
+ tls_comp_len = tls_len - (AES_BLOCK_LEN + *trailer_len);
+ memset(&uio, 0, sizeof(uio));
+
+ /*
+ * Allocate and populate the iov. Have to skip over the TLS
+ * header in 'm' as it is not part of the MAC input.
+ */
+ iovcnt = 1;
+ for (n = m; n != NULL; n = n->m_next)
+ iovcnt++;
+ iov = malloc(iovcnt * sizeof(*iov), M_KTLS_OCF, M_WAITOK);
+ iov[0].iov_base = &ad;
+ iov[0].iov_len = sizeof(ad);
+ skip = sizeof(*hdr) + AES_BLOCK_LEN;
+ for (i = 1, n = m; n != NULL; i++, n = n->m_next) {
+ if (n->m_len < skip) {
+ skip -= n->m_len;
+ continue;
+ }
+ iov[i].iov_base = mtod(n, char *) + skip;
+ iov[i].iov_len = n->m_len - skip;
+ skip = 0;
+ }
+ uio.uio_iov = iov;
+ uio.uio_iovcnt = i;
+ uio.uio_segflg = UIO_SYSSPACE;
+ uio.uio_td = curthread;
+ uio.uio_resid = sizeof(ad) + tls_len - AES_BLOCK_LEN;
+
+ /* Initialize the AAD. */
+ ad.seq = htobe64(seqno);
+ ad.type = hdr->tls_type;
+ ad.tls_vmajor = hdr->tls_vmajor;
+ ad.tls_vminor = hdr->tls_vminor;
+ ad.tls_length = htons(tls_comp_len);
+
+ crypto_initreq(&crp, os->mac_sid);
+ crp.crp_payload_start = 0;
+ crp.crp_payload_length = sizeof(ad) + tls_comp_len;
+ crp.crp_digest_start = crp.crp_payload_length;
+ crp.crp_op = CRYPTO_OP_VERIFY_DIGEST;
+ crp.crp_flags = CRYPTO_F_CBIMM;
+ crypto_use_uio(&crp, &uio);
+ error = ktls_ocf_dispatch(os, &crp);
+
+ crypto_destroyreq(&crp);
+ free(iov, M_KTLS_OCF);
+ return (error);
+}
+
static const struct ktls_ocf_sw ktls_ocf_tls_cbc_sw = {
- .encrypt = ktls_ocf_tls_cbc_encrypt
+ .encrypt = ktls_ocf_tls_cbc_encrypt,
+ .decrypt = ktls_ocf_tls_cbc_decrypt
};
static int
@@ -912,8 +1038,9 @@
tls->params.tls_vminor > TLS_MINOR_VER_TWO)
return (EPROTONOSUPPORT);
- /* AES-CBC is not supported for receive. */
- if (direction == KTLS_RX)
+ /* AES-CBC is not supported for receive for TLS 1.0. */
+ if (direction == KTLS_RX &&
+ tls->params.tls_vminor == TLS_MINOR_VER_ZERO)
return (EPROTONOSUPPORT);
csp.csp_flags |= CSP_F_SEPARATE_OUTPUT;

File Metadata

Mime Type
text/plain
Expires
Mon, Feb 10, 6:23 PM (7 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16581568
Default Alt Text
D37370.diff (5 KB)

Event Timeline