From nobody Tue Nov 15 20:04:17 2022 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4NBcZn5np5z4hdTD; Tue, 15 Nov 2022 20:04:17 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4NBcZn53Z2z4Mrc; Tue, 15 Nov 2022 20:04:17 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1668542657; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=jxiSjl+Rl43bk20NbYWiP7uaNbDbk1b5STotj3f8grs=; b=O5bL0ocX93MZAvFltO8xh8zEwZ7IDrpZIBqzskaLgQZRo/VTM2V6vH80rA+zCu34Df0uIt 7TiJfdMRKBKq055xGpRE5ZD4lQLM4jJNVakn7gC7uqb1pJ347vI5JrL5leVnGetlC4sMPn LrXIiLkwZKmBjZCdQIiyE0D4eGT3ASthyXecSXNU6dun1btt3vCgLgL1jaHksi5nTEmE98 vc+wxZxvdTKQULlqsfY/0ARHTpTxmCqprOqDY3cXtgWgWQniUtZ58/vl7Wq1gcqHpBGFzw eQb8syfUTsf7bm3PCNs5eMHUqsv5K4g0eWsBV1kOog2vursJ+3aZ3hjVofjvJg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1668542657; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=jxiSjl+Rl43bk20NbYWiP7uaNbDbk1b5STotj3f8grs=; b=m09SkauJv+3F+GCZ5tCZYkWUkS6AOGjJgBTAW6GLxKJXtdU3E9lulaHCDZnyUNN6ejJQAT Wt+0Yfuh/bHsRoxEE8R9Fry1nBD9fHUAZL6VI9i+RnpeN6MHxourBCu4Kc1JaiDnkrzB2c GZeu9xEPpugYEnZ3gqTf2lFHcoooPmfTf3UGmAfs7/VYGPTiiysJhMOgWNNMI2caNwOqAo /50POEZvnCtVOSPEaZqPfZtnSd2FjyDnwu9hHGDLIvHEa1LcBCV7c1K9PU6tP9dzuD4tbM fm3rEaU0FZbzYBhCeLTzpLHtLt4AzidCoOCkdx5i5/U2qTMApycpn35FI95gag== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1668542657; a=rsa-sha256; cv=none; b=s5d3PjPswH/hZ5+rMN4DIBHHdAyO+6UhHc7RvS6jCyr6inwf9HeXDMhxTt2pIriTkvQCPW qHkQcS98fpQMdsgkblV/527t7tM2h7p3ZmcJWAGznqjY0KslNSHeXtbCf/BnyXDq44ssCA cg3v6kUjV4IieI04FOqKk5vPywRychBI3Sf2S+M0Zoy+vxucDIlhijcEekPyRHF9GIe+U0 +lQGg/3r1QUPSX1g6SLSJagq3YBFaRTqKjEUW7BlWJJoohvnS/5nDgtjlfRL0CvK6yXecv SiUXsf7zAAGyk3huPhgKz3OQKVZ/IXtJMk2xx2FchLvqzcpWzml0jH42haiEkg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4NBcZn45SWzbHj; Tue, 15 Nov 2022 20:04:17 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 2AFK4HCY029288; Tue, 15 Nov 2022 20:04:17 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 2AFK4HJI029287; Tue, 15 Nov 2022 20:04:17 GMT (envelope-from git) Date: Tue, 15 Nov 2022 20:04:17 GMT Message-Id: <202211152004.2AFK4HJI029287@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: John Baldwin Subject: git: 9a673b715897 - main - ktls: Add software support for AES-CBC decryption for TLS 1.1+. List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jhb X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 9a673b7158973d86558a5d381e4784a561576b98 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=9a673b7158973d86558a5d381e4784a561576b98 commit 9a673b7158973d86558a5d381e4784a561576b98 Author: John Baldwin AuthorDate: 2022-11-15 20:02:03 +0000 Commit: John Baldwin CommitDate: 2022-11-15 20:02:03 +0000 ktls: Add software support for AES-CBC decryption for TLS 1.1+. This is mainly intended to provide a fallback for TOE TLS which may need to use software decryption for an initial record at the start of a connection. Reviewed by: markj Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D37370 --- sys/kern/uipc_ktls.c | 6 ++- sys/opencrypto/ktls_ocf.c | 133 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 134 insertions(+), 5 deletions(-) diff --git a/sys/kern/uipc_ktls.c b/sys/kern/uipc_ktls.c index 3df1f2843c32..ae9201976988 100644 --- a/sys/kern/uipc_ktls.c +++ b/sys/kern/uipc_ktls.c @@ -149,7 +149,7 @@ SYSCTL_BOOL(_kern_ipc_tls, OID_AUTO, enable, CTLFLAG_RWTUN, 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 @@ ktls_decrypt(struct socket *so) 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 index 6347ca459646..938133fa451a 100644 --- a/sys/opencrypto/ktls_ocf.c +++ b/sys/opencrypto/ktls_ocf.c @@ -101,6 +101,11 @@ SYSCTL_COUNTER_U64(_kern_ipc_tls_stats_ocf, OID_AUTO, tls10_cbc_encrypts, 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 @@ ktls_ocf_tls_cbc_encrypt(struct ktls_ocf_encrypt_state *state, 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 @@ ktls_ocf_try(struct socket *so, struct ktls_session *tls, int direction) 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;