[PATCH 07/16] crypto/cnxk: validate TLS xform and keys before SA key copy

Tejasree Kondoj ktejasree at marvell.com
Mon Oct 19 15:07:48 CEST 2026


From: Rupesh Chiluka <rchiluka at marvell.com>

cn10k_tls_record_session_update() and cn20k_tls_record_session_update()
forwarded the crypto_xform to tls_write_sa_fill() without running
cnxk_tls_xform_verify(), unlike the create path.

Separately, the AEAD key-length guard in the SA fill routines used a
single 16/32 check that incorrectly accepted a 16-byte
ChaCha20-Poly1305 key (ChaCha requires 32), and both the AEAD and the
read-side cipher paths copied key.data without a NULL check, so a
malformed xform could crash in memcpy().

- Call cnxk_tls_xform_verify() on the update path.
- Make the AEAD key-length validation algorithm-specific (AES-GCM
  16/32, ChaCha20-Poly1305 32, reject others).
- Reject NULL key pointers before the memcpy on both the AEAD and
  cipher paths, for cn10k and cn20k.

Signed-off-by: Rupesh Chiluka <rchiluka at marvell.com>
---
 drivers/crypto/cnxk/cn10k_tls.c | 33 +++++++++++++++++++++----
 drivers/crypto/cnxk/cn20k_tls.c | 44 +++++++++++++++++++++++++--------
 2 files changed, 62 insertions(+), 15 deletions(-)

diff --git a/drivers/crypto/cnxk/cn10k_tls.c b/drivers/crypto/cnxk/cn10k_tls.c
index 1a7b87e400..8aa6d5ad4b 100644
--- a/drivers/crypto/cnxk/cn10k_tls.c
+++ b/drivers/crypto/cnxk/cn10k_tls.c
@@ -358,19 +358,25 @@ tls_read_sa_fill(struct roc_ie_ot_tls_read_sa *read_sa,
 	if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
 		length = crypto_xfrm->aead.key.length;
 		if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_AES_GCM) {
+			if (length != 16 && length != 32)
+				return -EINVAL;
 			read_sa->w2.s.cipher_select = ROC_IE_OT_TLS_CIPHER_AES_GCM;
 			if (length == 16)
 				read_sa->w2.s.aes_key_len = ROC_IE_OT_TLS_AES_KEY_LEN_128;
 			else
 				read_sa->w2.s.aes_key_len = ROC_IE_OT_TLS_AES_KEY_LEN_256;
-		}
-
-		if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) {
+		} else if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) {
+			if (length != 32)
+				return -EINVAL;
 			read_sa->w2.s.cipher_select = ROC_IE_OT_TLS_CIPHER_CHACHA_POLY;
 			read_sa->w2.s.aes_key_len = ROC_IE_OT_TLS_AES_KEY_LEN_256;
+		} else {
+			return -EINVAL;
 		}
 
 		key = crypto_xfrm->aead.key.data;
+		if (key == NULL)
+			return -EINVAL;
 		memcpy(cipher_key, key, length);
 
 		if (tls_ver == RTE_SECURITY_VERSION_TLS_1_2)
@@ -395,6 +401,8 @@ tls_read_sa_fill(struct roc_ie_ot_tls_read_sa *read_sa,
 		if (cipher_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_3DES_CBC) {
 			read_sa->w2.s.cipher_select = ROC_IE_OT_TLS_CIPHER_3DES;
 			length = cipher_xfrm->cipher.key.length;
+			if (length != 24)
+				return -EINVAL;
 		} else if (cipher_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_AES_CBC) {
 			read_sa->w2.s.cipher_select = ROC_IE_OT_TLS_CIPHER_AES_CBC;
 			length = cipher_xfrm->cipher.key.length;
@@ -409,6 +417,8 @@ tls_read_sa_fill(struct roc_ie_ot_tls_read_sa *read_sa,
 		}
 
 		key = cipher_xfrm->cipher.key.data;
+		if (key == NULL || length == 0)
+			return -EINVAL;
 		memcpy(cipher_key, key, length);
 	}
 
@@ -515,18 +525,25 @@ tls_write_sa_fill(struct roc_ie_ot_tls_write_sa *write_sa,
 	if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
 		length = crypto_xfrm->aead.key.length;
 		if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_AES_GCM) {
+			if (length != 16 && length != 32)
+				return -EINVAL;
 			write_sa->w2.s.cipher_select = ROC_IE_OT_TLS_CIPHER_AES_GCM;
 			if (length == 16)
 				write_sa->w2.s.aes_key_len = ROC_IE_OT_TLS_AES_KEY_LEN_128;
 			else
 				write_sa->w2.s.aes_key_len = ROC_IE_OT_TLS_AES_KEY_LEN_256;
-		}
-		if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) {
+		} else if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) {
+			if (length != 32)
+				return -EINVAL;
 			write_sa->w2.s.cipher_select = ROC_IE_OT_TLS_CIPHER_CHACHA_POLY;
 			write_sa->w2.s.aes_key_len = ROC_IE_OT_TLS_AES_KEY_LEN_256;
+		} else {
+			return -EINVAL;
 		}
 
 		key = crypto_xfrm->aead.key.data;
+		if (key == NULL)
+			return -EINVAL;
 		memcpy(cipher_key, key, length);
 
 		if (tls_ver == RTE_SECURITY_VERSION_TLS_1_2)
@@ -551,6 +568,8 @@ tls_write_sa_fill(struct roc_ie_ot_tls_write_sa *write_sa,
 		if (cipher_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_3DES_CBC) {
 			write_sa->w2.s.cipher_select = ROC_IE_OT_TLS_CIPHER_3DES;
 			length = cipher_xfrm->cipher.key.length;
+			if (length != 24)
+				return -EINVAL;
 		} else if (cipher_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_AES_CBC) {
 			write_sa->w2.s.cipher_select = ROC_IE_OT_TLS_CIPHER_AES_CBC;
 			length = cipher_xfrm->cipher.key.length;
@@ -833,6 +852,10 @@ cn10k_tls_record_session_update(struct cnxk_cpt_vf *vf, struct cnxk_cpt_qp *qp,
 	if (conf->tls_record.type == RTE_SECURITY_TLS_SESS_TYPE_READ)
 		return -ENOTSUP;
 
+	ret = cnxk_tls_xform_verify(&conf->tls_record, conf->crypto_xform);
+	if (ret)
+		return ret;
+
 	roc_cpt = &vf->cpt;
 	ret = cn10k_tls_write_sa_create(roc_cpt, &qp->lf, &conf->tls_record, conf->crypto_xform,
 					(struct cn10k_sec_session *)sess);
diff --git a/drivers/crypto/cnxk/cn20k_tls.c b/drivers/crypto/cnxk/cn20k_tls.c
index 882d193c25..ac6f6d9c4b 100644
--- a/drivers/crypto/cnxk/cn20k_tls.c
+++ b/drivers/crypto/cnxk/cn20k_tls.c
@@ -249,19 +249,25 @@ tls_read_sa_fill(struct roc_ie_ow_tls_read_sa *read_sa,
 	if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
 		length = crypto_xfrm->aead.key.length;
 		if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_AES_GCM) {
+			if (length != 16 && length != 32)
+				return -EINVAL;
 			read_sa->w2.s.cipher_select = ROC_IE_OW_TLS_CIPHER_AES_GCM;
 			if (length == 16)
 				read_sa->w2.s.aes_key_len = ROC_IE_OW_TLS_AES_KEY_LEN_128;
 			else
 				read_sa->w2.s.aes_key_len = ROC_IE_OW_TLS_AES_KEY_LEN_256;
-		}
-
-		if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) {
+		} else if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) {
+			if (length != 32)
+				return -EINVAL;
 			read_sa->w2.s.cipher_select = ROC_IE_OW_TLS_CIPHER_CHACHA_POLY;
 			read_sa->w2.s.aes_key_len = ROC_IE_OW_TLS_AES_KEY_LEN_256;
+		} else {
+			return -EINVAL;
 		}
 
 		key = crypto_xfrm->aead.key.data;
+		if (key == NULL)
+			return -EINVAL;
 		memcpy(cipher_key, key, length);
 
 		if (tls_ver == RTE_SECURITY_VERSION_TLS_1_2)
@@ -286,6 +292,8 @@ tls_read_sa_fill(struct roc_ie_ow_tls_read_sa *read_sa,
 		if (cipher_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_3DES_CBC) {
 			read_sa->w2.s.cipher_select = ROC_IE_OW_TLS_CIPHER_3DES;
 			length = cipher_xfrm->cipher.key.length;
+			if (length != 24)
+				return -EINVAL;
 		} else if (cipher_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_AES_CBC) {
 			read_sa->w2.s.cipher_select = ROC_IE_OW_TLS_CIPHER_AES_CBC;
 			length = cipher_xfrm->cipher.key.length;
@@ -300,6 +308,8 @@ tls_read_sa_fill(struct roc_ie_ow_tls_read_sa *read_sa,
 		}
 
 		key = cipher_xfrm->cipher.key.data;
+		if (key == NULL || length == 0)
+			return -EINVAL;
 		memcpy(cipher_key, key, length);
 	}
 
@@ -576,18 +586,25 @@ tls_write_sa_fill(struct roc_ie_ow_tls_write_sa *write_sa,
 	if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
 		length = crypto_xfrm->aead.key.length;
 		if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_AES_GCM) {
+			if (length != 16 && length != 32)
+				return -EINVAL;
 			write_sa->w2.s.cipher_select = ROC_IE_OW_TLS_CIPHER_AES_GCM;
 			if (length == 16)
 				write_sa->w2.s.aes_key_len = ROC_IE_OW_TLS_AES_KEY_LEN_128;
 			else
 				write_sa->w2.s.aes_key_len = ROC_IE_OW_TLS_AES_KEY_LEN_256;
-		}
-		if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) {
+		} else if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) {
+			if (length != 32)
+				return -EINVAL;
 			write_sa->w2.s.cipher_select = ROC_IE_OW_TLS_CIPHER_CHACHA_POLY;
 			write_sa->w2.s.aes_key_len = ROC_IE_OW_TLS_AES_KEY_LEN_256;
+		} else {
+			return -EINVAL;
 		}
 
 		key = crypto_xfrm->aead.key.data;
+		if (key == NULL)
+			return -EINVAL;
 		memcpy(cipher_key, key, length);
 
 		if (tls_ver == RTE_SECURITY_VERSION_TLS_1_2)
@@ -612,6 +629,8 @@ tls_write_sa_fill(struct roc_ie_ow_tls_write_sa *write_sa,
 		if (cipher_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_3DES_CBC) {
 			write_sa->w2.s.cipher_select = ROC_IE_OW_TLS_CIPHER_3DES;
 			length = cipher_xfrm->cipher.key.length;
+			if (length != 24)
+				return -EINVAL;
 		} else if (cipher_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_AES_CBC) {
 			write_sa->w2.s.cipher_select = ROC_IE_OW_TLS_CIPHER_AES_CBC;
 			length = cipher_xfrm->cipher.key.length;
@@ -626,10 +645,9 @@ tls_write_sa_fill(struct roc_ie_ow_tls_write_sa *write_sa,
 		}
 
 		key = cipher_xfrm->cipher.key.data;
-		if (key != NULL && length != 0) {
-			/* Copy encryption key */
-			memcpy(cipher_key, key, length);
-		}
+		if (key == NULL)
+			return -EINVAL;
+		memcpy(cipher_key, key, length);
 	}
 
 	if (auth_xfrm != NULL) {
@@ -716,7 +734,6 @@ cn20k_tls_write_sa_create(struct roc_cpt *roc_cpt, struct roc_cpt_lf *lf,
 		plt_err("Couldn't allocate memory for WRITE SA");
 		return -ENOMEM;
 	}
-	tls->write_sa = write_sa;
 
 	/* Allocate memory to be used as dptr for CPT ucode WRITE_SA op */
 	sa_dptr = plt_zmalloc(sizeof(struct roc_ie_ow_tls_write_sa), 8);
@@ -782,6 +799,9 @@ cn20k_tls_write_sa_create(struct roc_cpt *roc_cpt, struct roc_cpt_lf *lf,
 
 	rte_atomic_thread_fence(rte_memory_order_seq_cst);
 
+	if (tls->write_sa != NULL)
+		rte_free(tls->write_sa);
+	tls->write_sa = write_sa;
 sa_dptr_free:
 	plt_free(sa_dptr);
 sa_cptr_free:
@@ -834,6 +854,10 @@ cn20k_tls_record_session_update(struct cnxk_cpt_vf *vf, struct cnxk_cpt_qp *qp,
 	if (conf->tls_record.type == RTE_SECURITY_TLS_SESS_TYPE_READ)
 		return -ENOTSUP;
 
+	ret = cnxk_tls_xform_verify(&conf->tls_record, conf->crypto_xform);
+	if (ret)
+		return ret;
+
 	roc_cpt = &vf->cpt;
 	ret = cn20k_tls_write_sa_create(roc_cpt, &qp->lf, &conf->tls_record, conf->crypto_xform,
 					(struct cn20k_sec_session *)sess);
-- 
2.43.0



More information about the dev mailing list