[PATCH] common/cnxk: validate xform in inline IPsec session create

Aarnav JP ajp at marvell.com
Thu Jul 23 14:15:09 CEST 2026


Add cnxk_ipsec_xform_verify() call in cn10k, cn20k and cn9k
inline IPsec session create paths to reject invalid crypto
transforms early, before any SA memory is written. Previously
this validation was only performed in the lookaside crypto
paths, allowing the inline paths to reach SA fill helpers
with unchecked key lengths and algorithm combinations.

Move the xform verification helpers from the crypto driver
private header to the shared cnxk_security.h so they are
accessible to both the net and crypto drivers.

Drop the aead.op vs direction consistency check from the
shared verifier since the cnxk driver derives SA direction
from ipsec_xform.direction and does not use aead.op.

Fixes: 69daa9e5022b ("net/cnxk: support inline security setup for cn10k")
Fixes: 7eabd6c63773 ("net/cnxk: support inline security setup for cn9k")
Fixes: 7eaa499dd0c2 ("net/cnxk: support CN20K inline IPsec session")
Cc: stable at dpdk.org

Signed-off-by: Aarnav JP <ajp at marvell.com>
---
 drivers/common/cnxk/cnxk_security.h | 175 ++++++++++++++++++++++++++
 drivers/crypto/cnxk/cnxk_ipsec.h    | 183 +---------------------------
 drivers/net/cnxk/cn10k_ethdev_sec.c |   7 ++
 drivers/net/cnxk/cn20k_ethdev_sec.c |   7 ++
 drivers/net/cnxk/cn9k_ethdev_sec.c  |   7 ++
 5 files changed, 197 insertions(+), 182 deletions(-)

diff --git a/drivers/common/cnxk/cnxk_security.h b/drivers/common/cnxk/cnxk_security.h
index 3912c8d376..10e7d5b520 100644
--- a/drivers/common/cnxk/cnxk_security.h
+++ b/drivers/common/cnxk/cnxk_security.h
@@ -4,6 +4,8 @@
 #ifndef _CNXK_SECURITY_H__
 #define _CNXK_SECURITY_H__
 
+#include <errno.h>
+
 #include <rte_crypto.h>
 #include <rte_security.h>
 
@@ -65,4 +67,177 @@ int __roc_api cnxk_ow_ipsec_outb_sa_fill(struct roc_ow_ipsec_outb_sa *sa,
 					 uint8_t ctx_ilen);
 bool __roc_api cnxk_ow_ipsec_inb_sa_valid(struct roc_ow_ipsec_inb_sa *sa);
 bool __roc_api cnxk_ow_ipsec_outb_sa_valid(struct roc_ow_ipsec_outb_sa *sa);
+
+static inline int
+ipsec_xform_cipher_verify(struct rte_crypto_sym_xform *crypto_xform)
+{
+	if (crypto_xform->cipher.algo == RTE_CRYPTO_CIPHER_NULL)
+		return 0;
+
+	if (crypto_xform->cipher.algo == RTE_CRYPTO_CIPHER_DES_CBC &&
+	    crypto_xform->cipher.key.length == 8)
+		return 0;
+
+	if (crypto_xform->cipher.algo == RTE_CRYPTO_CIPHER_AES_CBC ||
+	    crypto_xform->cipher.algo == RTE_CRYPTO_CIPHER_AES_CTR) {
+		switch (crypto_xform->cipher.key.length) {
+		case 16:
+		case 24:
+		case 32:
+			break;
+		default:
+			return -ENOTSUP;
+		}
+		return 0;
+	}
+
+	if (crypto_xform->cipher.algo == RTE_CRYPTO_CIPHER_3DES_CBC &&
+	    crypto_xform->cipher.key.length == 24)
+		return 0;
+
+	return -ENOTSUP;
+}
+
+static inline int
+ipsec_xform_auth_verify(struct rte_crypto_sym_xform *crypto_xform)
+{
+	uint16_t keylen = crypto_xform->auth.key.length;
+
+	if (crypto_xform->auth.algo == RTE_CRYPTO_AUTH_NULL)
+		return 0;
+
+	if (crypto_xform->auth.algo == RTE_CRYPTO_AUTH_MD5_HMAC) {
+		if (keylen == 16)
+			return 0;
+	}
+
+	if (crypto_xform->auth.algo == RTE_CRYPTO_AUTH_SHA1_HMAC) {
+		if (keylen >= 20 && keylen <= 64)
+			return 0;
+	} else if (crypto_xform->auth.algo == RTE_CRYPTO_AUTH_SHA256_HMAC) {
+		if (keylen >= 32 && keylen <= 64)
+			return 0;
+	} else if (crypto_xform->auth.algo == RTE_CRYPTO_AUTH_SHA384_HMAC) {
+		if (keylen == 48)
+			return 0;
+	} else if (crypto_xform->auth.algo == RTE_CRYPTO_AUTH_SHA512_HMAC) {
+		if (keylen == 64)
+			return 0;
+	} else if (crypto_xform->auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) {
+		if (keylen >= 16 && keylen <= 32)
+			return 0;
+	}
+
+	if (crypto_xform->auth.algo == RTE_CRYPTO_AUTH_AES_XCBC_MAC &&
+	    keylen == ROC_CPT_AES_XCBC_KEY_LENGTH)
+		return 0;
+
+	return -ENOTSUP;
+}
+
+static inline int
+ipsec_xform_aead_verify(struct rte_security_ipsec_xform *ipsec_xform __rte_unused,
+			struct rte_crypto_sym_xform *crypto_xform)
+{
+	if (crypto_xform->aead.algo == RTE_CRYPTO_AEAD_AES_GCM ||
+	    crypto_xform->aead.algo == RTE_CRYPTO_AEAD_AES_CCM) {
+		switch (crypto_xform->aead.key.length) {
+		case 16:
+		case 24:
+		case 32:
+			break;
+		default:
+			return -EINVAL;
+		}
+		return 0;
+	}
+
+	return -ENOTSUP;
+}
+
+static inline int
+cnxk_ipsec_xform_verify(struct rte_security_ipsec_xform *ipsec_xform,
+			struct rte_crypto_sym_xform *crypto_xform)
+{
+	struct rte_crypto_sym_xform *auth_xform, *cipher_xform;
+	int ret;
+
+	if ((ipsec_xform->direction != RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
+	    (ipsec_xform->direction != RTE_SECURITY_IPSEC_SA_DIR_EGRESS))
+		return -EINVAL;
+
+	if ((ipsec_xform->proto != RTE_SECURITY_IPSEC_SA_PROTO_ESP) &&
+	    (ipsec_xform->proto != RTE_SECURITY_IPSEC_SA_PROTO_AH))
+		return -EINVAL;
+
+	if ((ipsec_xform->mode != RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT) &&
+	    (ipsec_xform->mode != RTE_SECURITY_IPSEC_SA_MODE_TUNNEL))
+		return -EINVAL;
+
+	if ((ipsec_xform->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) &&
+	    (ipsec_xform->tunnel.type != RTE_SECURITY_IPSEC_TUNNEL_IPV4) &&
+	    (ipsec_xform->tunnel.type != RTE_SECURITY_IPSEC_TUNNEL_IPV6))
+		return -EINVAL;
+
+	if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
+		if (ipsec_xform->proto != RTE_SECURITY_IPSEC_SA_PROTO_ESP)
+			return -EINVAL;
+		return ipsec_xform_aead_verify(ipsec_xform, crypto_xform);
+	}
+
+	if (ipsec_xform->proto == RTE_SECURITY_IPSEC_SA_PROTO_AH) {
+		if (ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
+			/* Ingress */
+			auth_xform = crypto_xform;
+			cipher_xform = crypto_xform->next;
+
+			if (crypto_xform->type != RTE_CRYPTO_SYM_XFORM_AUTH)
+				return -EINVAL;
+
+			if ((cipher_xform != NULL) &&
+			    ((cipher_xform->type != RTE_CRYPTO_SYM_XFORM_CIPHER) ||
+			     (cipher_xform->cipher.algo != RTE_CRYPTO_CIPHER_NULL)))
+				return -EINVAL;
+		} else {
+			/* Egress */
+			if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
+				cipher_xform = crypto_xform;
+				auth_xform = crypto_xform->next;
+
+				if (auth_xform == NULL ||
+				    cipher_xform->cipher.algo != RTE_CRYPTO_CIPHER_NULL)
+					return -EINVAL;
+			} else if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AUTH)
+				auth_xform = crypto_xform;
+			else
+				return -EINVAL;
+		}
+	} else {
+		if (crypto_xform->next == NULL)
+			return -EINVAL;
+
+		if (ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
+			/* Ingress */
+			if (crypto_xform->type != RTE_CRYPTO_SYM_XFORM_AUTH ||
+			    crypto_xform->next->type != RTE_CRYPTO_SYM_XFORM_CIPHER)
+				return -EINVAL;
+			auth_xform = crypto_xform;
+			cipher_xform = crypto_xform->next;
+		} else {
+			/* Egress */
+			if (crypto_xform->type != RTE_CRYPTO_SYM_XFORM_CIPHER ||
+			    crypto_xform->next->type != RTE_CRYPTO_SYM_XFORM_AUTH)
+				return -EINVAL;
+			cipher_xform = crypto_xform;
+			auth_xform = crypto_xform->next;
+		}
+
+		ret = ipsec_xform_cipher_verify(cipher_xform);
+		if (ret)
+			return ret;
+	}
+
+	return ipsec_xform_auth_verify(auth_xform);
+}
+
 #endif /* _CNXK_SECURITY_H__ */
diff --git a/drivers/crypto/cnxk/cnxk_ipsec.h b/drivers/crypto/cnxk/cnxk_ipsec.h
index 5f65c34380..2ca3c2525c 100644
--- a/drivers/crypto/cnxk/cnxk_ipsec.h
+++ b/drivers/crypto/cnxk/cnxk_ipsec.h
@@ -7,6 +7,7 @@
 #include <rte_security.h>
 #include <rte_security_driver.h>
 
+#include "cnxk_security.h"
 #include "roc_cpt.h"
 #include "roc_ie_on.h"
 #include "roc_ie_ot.h"
@@ -21,186 +22,4 @@ struct cnxk_cpt_inst_tmpl {
 	uint64_t w7;
 };
 
-static inline int
-ipsec_xform_cipher_verify(struct rte_crypto_sym_xform *crypto_xform)
-{
-	if (crypto_xform->cipher.algo == RTE_CRYPTO_CIPHER_NULL)
-		return 0;
-
-	if (crypto_xform->cipher.algo == RTE_CRYPTO_CIPHER_DES_CBC &&
-	    crypto_xform->cipher.key.length == 8)
-		return 0;
-
-	if (crypto_xform->cipher.algo == RTE_CRYPTO_CIPHER_AES_CBC ||
-	    crypto_xform->cipher.algo == RTE_CRYPTO_CIPHER_AES_CTR) {
-		switch (crypto_xform->cipher.key.length) {
-		case 16:
-		case 24:
-		case 32:
-			break;
-		default:
-			return -ENOTSUP;
-		}
-		return 0;
-	}
-
-	if (crypto_xform->cipher.algo == RTE_CRYPTO_CIPHER_3DES_CBC &&
-	    crypto_xform->cipher.key.length == 24)
-		return 0;
-
-	return -ENOTSUP;
-}
-
-static inline int
-ipsec_xform_auth_verify(struct rte_crypto_sym_xform *crypto_xform)
-{
-	uint16_t keylen = crypto_xform->auth.key.length;
-
-	if (crypto_xform->auth.algo == RTE_CRYPTO_AUTH_NULL)
-		return 0;
-
-	if (crypto_xform->auth.algo == RTE_CRYPTO_AUTH_MD5_HMAC) {
-		if (keylen == 16)
-			return 0;
-	}
-
-	if (crypto_xform->auth.algo == RTE_CRYPTO_AUTH_SHA1_HMAC) {
-		if (keylen >= 20 && keylen <= 64)
-			return 0;
-	} else if (crypto_xform->auth.algo == RTE_CRYPTO_AUTH_SHA256_HMAC) {
-		if (keylen >= 32 && keylen <= 64)
-			return 0;
-	} else if (crypto_xform->auth.algo == RTE_CRYPTO_AUTH_SHA384_HMAC) {
-		if (keylen == 48)
-			return 0;
-	} else if (crypto_xform->auth.algo == RTE_CRYPTO_AUTH_SHA512_HMAC) {
-		if (keylen == 64)
-			return 0;
-	} else if (crypto_xform->auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) {
-		if (keylen >= 16 && keylen <= 32)
-			return 0;
-	}
-
-	if (crypto_xform->auth.algo == RTE_CRYPTO_AUTH_AES_XCBC_MAC &&
-	    keylen == ROC_CPT_AES_XCBC_KEY_LENGTH)
-		return 0;
-
-	return -ENOTSUP;
-}
-
-static inline int
-ipsec_xform_aead_verify(struct rte_security_ipsec_xform *ipsec_xform,
-			struct rte_crypto_sym_xform *crypto_xform)
-{
-	if (ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS &&
-	    crypto_xform->aead.op != RTE_CRYPTO_AEAD_OP_ENCRYPT)
-		return -EINVAL;
-
-	if (ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS &&
-	    crypto_xform->aead.op != RTE_CRYPTO_AEAD_OP_DECRYPT)
-		return -EINVAL;
-
-	if (crypto_xform->aead.algo == RTE_CRYPTO_AEAD_AES_GCM ||
-	    crypto_xform->aead.algo == RTE_CRYPTO_AEAD_AES_CCM) {
-		switch (crypto_xform->aead.key.length) {
-		case 16:
-		case 24:
-		case 32:
-			break;
-		default:
-			return -EINVAL;
-		}
-		return 0;
-	}
-
-	return -ENOTSUP;
-}
-
-static inline int
-cnxk_ipsec_xform_verify(struct rte_security_ipsec_xform *ipsec_xform,
-			struct rte_crypto_sym_xform *crypto_xform)
-{
-	struct rte_crypto_sym_xform *auth_xform, *cipher_xform;
-	int ret;
-
-	if ((ipsec_xform->direction != RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
-	    (ipsec_xform->direction != RTE_SECURITY_IPSEC_SA_DIR_EGRESS))
-		return -EINVAL;
-
-	if ((ipsec_xform->proto != RTE_SECURITY_IPSEC_SA_PROTO_ESP) &&
-	    (ipsec_xform->proto != RTE_SECURITY_IPSEC_SA_PROTO_AH))
-		return -EINVAL;
-
-	if ((ipsec_xform->mode != RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT) &&
-	    (ipsec_xform->mode != RTE_SECURITY_IPSEC_SA_MODE_TUNNEL))
-		return -EINVAL;
-
-	if ((ipsec_xform->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) &&
-	    (ipsec_xform->tunnel.type != RTE_SECURITY_IPSEC_TUNNEL_IPV4) &&
-	    (ipsec_xform->tunnel.type != RTE_SECURITY_IPSEC_TUNNEL_IPV6))
-		return -EINVAL;
-
-	if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD)
-		return ipsec_xform_aead_verify(ipsec_xform, crypto_xform);
-
-	if (ipsec_xform->proto == RTE_SECURITY_IPSEC_SA_PROTO_AH) {
-		if (ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
-			/* Ingress */
-			auth_xform = crypto_xform;
-			cipher_xform = crypto_xform->next;
-
-			if (crypto_xform->type != RTE_CRYPTO_SYM_XFORM_AUTH)
-				return -EINVAL;
-
-			if ((cipher_xform != NULL) && ((cipher_xform->type !=
-			    RTE_CRYPTO_SYM_XFORM_CIPHER) ||
-			    (cipher_xform->cipher.algo !=
-			    RTE_CRYPTO_CIPHER_NULL)))
-				return -EINVAL;
-		} else {
-				/* Egress */
-			if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
-				cipher_xform = crypto_xform;
-				auth_xform = crypto_xform->next;
-
-				if (auth_xform == NULL ||
-				    cipher_xform->cipher.algo !=
-				    RTE_CRYPTO_CIPHER_NULL)
-					return -EINVAL;
-			} else if (crypto_xform->type ==
-				   RTE_CRYPTO_SYM_XFORM_AUTH)
-				auth_xform = crypto_xform;
-			else
-				return -EINVAL;
-		}
-	} else {
-		if (crypto_xform->next == NULL)
-			return -EINVAL;
-
-		if (ipsec_xform->direction ==
-		    RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
-			/* Ingress */
-			if (crypto_xform->type != RTE_CRYPTO_SYM_XFORM_AUTH ||
-			    crypto_xform->next->type !=
-				    RTE_CRYPTO_SYM_XFORM_CIPHER)
-				return -EINVAL;
-			auth_xform = crypto_xform;
-			cipher_xform = crypto_xform->next;
-		} else {
-			/* Egress */
-			if (crypto_xform->type != RTE_CRYPTO_SYM_XFORM_CIPHER ||
-			    crypto_xform->next->type !=
-				    RTE_CRYPTO_SYM_XFORM_AUTH)
-				return -EINVAL;
-			cipher_xform = crypto_xform;
-			auth_xform = crypto_xform->next;
-		}
-
-		ret = ipsec_xform_cipher_verify(cipher_xform);
-		if (ret)
-			return ret;
-	}
-
-	return ipsec_xform_auth_verify(auth_xform);
-}
 #endif /* __CNXK_IPSEC_H__ */
diff --git a/drivers/net/cnxk/cn10k_ethdev_sec.c b/drivers/net/cnxk/cn10k_ethdev_sec.c
index 2f1fdf34fc..0682294099 100644
--- a/drivers/net/cnxk/cn10k_ethdev_sec.c
+++ b/drivers/net/cnxk/cn10k_ethdev_sec.c
@@ -785,6 +785,13 @@ cn10k_eth_sec_session_create(void *device,
 
 	ipsec = &conf->ipsec;
 	crypto = conf->crypto_xform;
+
+	rc = cnxk_ipsec_xform_verify(ipsec, crypto);
+	if (rc) {
+		plt_err("Crypto xform verify failed, rc=%d", rc);
+		return rc;
+	}
+
 	inbound = !!(ipsec->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
 	inl_dev = !!dev->inb.inl_dev;
 
diff --git a/drivers/net/cnxk/cn20k_ethdev_sec.c b/drivers/net/cnxk/cn20k_ethdev_sec.c
index a5be85901f..65f0235a46 100644
--- a/drivers/net/cnxk/cn20k_ethdev_sec.c
+++ b/drivers/net/cnxk/cn20k_ethdev_sec.c
@@ -817,6 +817,13 @@ cn20k_eth_sec_session_create(void *device, struct rte_security_session_conf *con
 
 	ipsec = &conf->ipsec;
 	crypto = conf->crypto_xform;
+
+	rc = cnxk_ipsec_xform_verify(ipsec, crypto);
+	if (rc) {
+		plt_err("Crypto xform verify failed, rc=%d", rc);
+		return rc;
+	}
+
 	inbound = !!(ipsec->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
 	inl_dev = !!dev->inb.inl_dev;
 
diff --git a/drivers/net/cnxk/cn9k_ethdev_sec.c b/drivers/net/cnxk/cn9k_ethdev_sec.c
index 5e13dc862e..4024b243d7 100644
--- a/drivers/net/cnxk/cn9k_ethdev_sec.c
+++ b/drivers/net/cnxk/cn9k_ethdev_sec.c
@@ -602,6 +602,13 @@ cn9k_eth_sec_session_create(void *device,
 
 	ipsec = &conf->ipsec;
 	crypto = conf->crypto_xform;
+
+	rc = cnxk_ipsec_xform_verify(ipsec, crypto);
+	if (rc) {
+		plt_err("Crypto xform verify failed, rc=%d", rc);
+		return rc;
+	}
+
 	inbound = !!(ipsec->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
 
 	lock = inbound ? &dev->inb.lock : &dev->outb.lock;
-- 
2.43.0



More information about the dev mailing list