git: 107daeb474b2 - stable/13 - ktls_ocf: Reject encrypted TLS records using AEAD that are too small.

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Tue, 24 Jan 2023 05:43:13 UTC
The branch stable/13 has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=107daeb474b29ec587dfe7d8cf686eda99094249

commit 107daeb474b29ec587dfe7d8cf686eda99094249
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2022-11-15 20:02:57 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2023-01-24 05:08:09 +0000

    ktls_ocf: Reject encrypted TLS records using AEAD that are too small.
    
    If a TLS record is too small to contain the required explicit IV,
    record_type (TLS 1.3), and MAC, reject attempts to decrypt it with
    EMSGSIZE without submitting it to OCF.  OCF drivers may not properly
    detect that regions in the crypto request are outside the bounds of
    the mbuf chain.  The caller isn't supposed to submit such requests.
    
    Reviewed by:    markj
    Sponsored by:   Chelsio Communications
    Differential Revision:  https://reviews.freebsd.org/D37372
    
    (cherry picked from commit 4e47414648894943413091984124d93bd43e5da1)
---
 sys/opencrypto/ktls_ocf.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/sys/opencrypto/ktls_ocf.c b/sys/opencrypto/ktls_ocf.c
index 56156b6a4988..805fab2ddac8 100644
--- a/sys/opencrypto/ktls_ocf.c
+++ b/sys/opencrypto/ktls_ocf.c
@@ -458,13 +458,19 @@ ktls_ocf_tls12_aead_decrypt(struct ktls_session *tls,
 	struct ocf_session *os;
 	struct ocf_operation oo;
 	int error;
-	uint16_t tls_comp_len;
+	uint16_t tls_comp_len, tls_len;
 
 	os = tls->cipher;
 
 	oo.os = os;
 	oo.done = false;
 
+	/* Ensure record contains at least an explicit IV and tag. */
+	tls_len = ntohs(hdr->tls_length);
+	if (tls_len + sizeof(*hdr) < tls->params.tls_hlen +
+	    tls->params.tls_tlen)
+		return (EMSGSIZE);
+
 	crypto_initreq(&crp, os->sid);
 
 	/* Setup the IV. */
@@ -484,10 +490,10 @@ ktls_ocf_tls12_aead_decrypt(struct ktls_session *tls,
 
 	/* Setup the AAD. */
 	if (tls->params.cipher_algorithm == CRYPTO_AES_NIST_GCM_16)
-		tls_comp_len = ntohs(hdr->tls_length) -
+		tls_comp_len = tls_len -
 		    (AES_GMAC_HASH_LEN + sizeof(uint64_t));
 	else
-		tls_comp_len = ntohs(hdr->tls_length) - POLY1305_HASH_LEN;
+		tls_comp_len = tls_len - POLY1305_HASH_LEN;
 	ad.seq = htobe64(seqno);
 	ad.type = hdr->tls_type;
 	ad.tls_vmajor = hdr->tls_vmajor;
@@ -619,14 +625,16 @@ ktls_ocf_tls13_aead_decrypt(struct ktls_session *tls,
 	struct ocf_session *os;
 	int error;
 	u_int tag_len;
+	uint16_t tls_len;
 
 	os = tls->cipher;
 
 	tag_len = tls->params.tls_tlen - 1;
 
 	/* Payload must contain at least one byte for the record type. */
-	if (ntohs(hdr->tls_length) < tag_len + 1)
-		return (EBADMSG);
+	tls_len = ntohs(hdr->tls_length);
+	if (tls_len < tag_len + 1)
+		return (EMSGSIZE);
 
 	crypto_initreq(&crp, os->sid);
 
@@ -643,7 +651,7 @@ ktls_ocf_tls13_aead_decrypt(struct ktls_session *tls,
 	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_payload_length = tls_len - tag_len;
 	crp.crp_digest_start = crp.crp_payload_start + crp.crp_payload_length;
 
 	crp.crp_op = CRYPTO_OP_DECRYPT | CRYPTO_OP_VERIFY_DIGEST;