On Thu, Jul 23, 2026 at 8:17 PM Aarnav JP <[email protected]> wrote:
>
> 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: [email protected]
>
> Signed-off-by: Aarnav JP <[email protected]>
Applied to dpdk-next-net-mrvl/for-main. Thanks
> ---
> 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
>