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
>

Reply via email to