[3/4] crypto/cnxk: add security session ops

Message ID 1622653862-22830-4-git-send-email-anoobj@marvell.com (mailing list archive)
State Superseded, archived
Delegated to: akhil goyal
Headers
Series Add rte_security in crypto_cn10k PMD |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Anoob Joseph June 2, 2021, 5:11 p.m. UTC
  From: Tejasree Kondoj <ktejasree@marvell.com>

Add security session ops in cn10k crypto PMD.

Signed-off-by: Anoob Joseph <anoobj@marvell.com>
Signed-off-by: Archana Muniganti <marchana@marvell.com>
Signed-off-by: Srujana Challa <schalla@marvell.com>
Signed-off-by: Tejasree Kondoj <ktejasree@marvell.com>
---
 drivers/crypto/cnxk/cn10k_cryptodev.c |   2 +
 drivers/crypto/cnxk/cn10k_ipsec.c     | 520 ++++++++++++++++++++++++++++++++++
 drivers/crypto/cnxk/cn10k_ipsec.h     |  38 +++
 drivers/crypto/cnxk/cnxk_ipsec.h      |  18 ++
 drivers/crypto/cnxk/meson.build       |   3 +-
 5 files changed, 580 insertions(+), 1 deletion(-)
 create mode 100644 drivers/crypto/cnxk/cn10k_ipsec.c
 create mode 100644 drivers/crypto/cnxk/cn10k_ipsec.h
 create mode 100644 drivers/crypto/cnxk/cnxk_ipsec.h
  

Comments

Akhil Goyal June 16, 2021, 8:11 p.m. UTC | #1
> diff --git a/drivers/crypto/cnxk/meson.build
> b/drivers/crypto/cnxk/meson.build
> index ab45483..eea08fa 100644
> --- a/drivers/crypto/cnxk/meson.build
> +++ b/drivers/crypto/cnxk/meson.build
> @@ -13,6 +13,7 @@ sources = files(
>          'cn9k_cryptodev_ops.c',
>          'cn10k_cryptodev.c',
>          'cn10k_cryptodev_ops.c',
> +        'cn10k_ipsec.c',
>          'cnxk_cpt_ops_helper.c',
>          'cnxk_cryptodev.c',
>          'cnxk_cryptodev_capabilities.c',
> @@ -20,4 +21,4 @@ sources = files(
>          'cnxk_cryptodev_sec.c',
>  )
> 
> -deps += ['bus_pci', 'common_cnxk', 'security']
> +deps += ['bus_pci', 'common_cnxk', 'security', 'rte_net']
> --
This should be 'net' and not 'rte_net'.
Do we really need this dependency?
  
Anoob Joseph June 17, 2021, 7:16 a.m. UTC | #2
Hi Akhil,

Please see inline.

Thanks,
Anoob

> -----Original Message-----
> From: Akhil Goyal <gakhil@marvell.com>
> Sent: Thursday, June 17, 2021 1:41 AM
> To: Anoob Joseph <anoobj@marvell.com>; Thomas Monjalon
> <thomas@monjalon.net>
> Cc: Tejasree Kondoj <ktejasree@marvell.com>; Jerin Jacob Kollanukkaran
> <jerinj@marvell.com>; Ankur Dwivedi <adwivedi@marvell.com>;
> dev@dpdk.org; Anoob Joseph <anoobj@marvell.com>; Archana Muniganti
> <marchana@marvell.com>; Srujana Challa <schalla@marvell.com>
> Subject: RE: [PATCH 3/4] crypto/cnxk: add security session ops
> 
> > diff --git a/drivers/crypto/cnxk/meson.build
> > b/drivers/crypto/cnxk/meson.build index ab45483..eea08fa 100644
> > --- a/drivers/crypto/cnxk/meson.build
> > +++ b/drivers/crypto/cnxk/meson.build
> > @@ -13,6 +13,7 @@ sources = files(
> >          'cn9k_cryptodev_ops.c',
> >          'cn10k_cryptodev.c',
> >          'cn10k_cryptodev_ops.c',
> > +        'cn10k_ipsec.c',
> >          'cnxk_cpt_ops_helper.c',
> >          'cnxk_cryptodev.c',
> >          'cnxk_cryptodev_capabilities.c', @@ -20,4 +21,4 @@ sources =
> > files(
> >          'cnxk_cryptodev_sec.c',
> >  )
> >
> > -deps += ['bus_pci', 'common_cnxk', 'security']
> > +deps += ['bus_pci', 'common_cnxk', 'security', 'rte_net']
> > --
> This should be 'net' and not 'rte_net'.
> Do we really need this dependency?

[Anoob] It was required since we had a dependency on rte_esp.h. But, as you said, we don't need to make it as dependency on 'net'. Something like,

includes += include_directories('../../../lib/net')

Is good enough. Will have this changed so.
  

Patch

diff --git a/drivers/crypto/cnxk/cn10k_cryptodev.c b/drivers/crypto/cnxk/cn10k_cryptodev.c
index b58d390..9517e62 100644
--- a/drivers/crypto/cnxk/cn10k_cryptodev.c
+++ b/drivers/crypto/cnxk/cn10k_cryptodev.c
@@ -12,6 +12,7 @@ 
 
 #include "cn10k_cryptodev.h"
 #include "cn10k_cryptodev_ops.h"
+#include "cn10k_ipsec.h"
 #include "cnxk_cryptodev.h"
 #include "cnxk_cryptodev_capabilities.h"
 #include "cnxk_cryptodev_sec.h"
@@ -97,6 +98,7 @@  cn10k_cpt_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 			     RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED;
 
 	cn10k_cpt_set_enqdeq_fns(dev);
+	cn10k_sec_ops_override();
 
 	return 0;
 
diff --git a/drivers/crypto/cnxk/cn10k_ipsec.c b/drivers/crypto/cnxk/cn10k_ipsec.c
new file mode 100644
index 0000000..31be6e7
--- /dev/null
+++ b/drivers/crypto/cnxk/cn10k_ipsec.c
@@ -0,0 +1,520 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+
+#include <rte_malloc.h>
+#include <rte_cryptodev.h>
+#include <rte_esp.h>
+#include <rte_ip.h>
+#include <rte_security.h>
+#include <rte_security_driver.h>
+#include <rte_udp.h>
+
+#include "cnxk_cryptodev.h"
+#include "cnxk_ipsec.h"
+#include "cn10k_ipsec.h"
+
+#include "roc_api.h"
+#include "roc_ie.h"
+
+static int
+ipsec_xform_aead_verify(struct rte_security_ipsec_xform *ipsec_xfrm,
+			struct rte_crypto_sym_xform *crypto_xfrm)
+{
+	if (ipsec_xfrm->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS &&
+	    crypto_xfrm->aead.op != RTE_CRYPTO_AEAD_OP_ENCRYPT)
+		return -EINVAL;
+
+	if (ipsec_xfrm->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS &&
+	    crypto_xfrm->aead.op != RTE_CRYPTO_AEAD_OP_DECRYPT)
+		return -EINVAL;
+
+	if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_AES_GCM) {
+		switch (crypto_xfrm->aead.key.length) {
+		case ROC_AES128_KEY_LEN:
+		case ROC_AES192_KEY_LEN:
+		case ROC_AES256_KEY_LEN:
+			break;
+		default:
+			return -EINVAL;
+		}
+		return 0;
+	}
+
+	return -ENOTSUP;
+}
+
+static int
+cn10k_ipsec_xform_verify(struct rte_security_ipsec_xform *ipsec_xfrm,
+			 struct rte_crypto_sym_xform *crypto_xfrm)
+{
+	if ((ipsec_xfrm->direction != RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
+	    (ipsec_xfrm->direction != RTE_SECURITY_IPSEC_SA_DIR_EGRESS))
+		return -EINVAL;
+
+	if ((ipsec_xfrm->proto != RTE_SECURITY_IPSEC_SA_PROTO_ESP) &&
+	    (ipsec_xfrm->proto != RTE_SECURITY_IPSEC_SA_PROTO_AH))
+		return -EINVAL;
+
+	if ((ipsec_xfrm->mode != RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT) &&
+	    (ipsec_xfrm->mode != RTE_SECURITY_IPSEC_SA_MODE_TUNNEL))
+		return -EINVAL;
+
+	if ((ipsec_xfrm->tunnel.type != RTE_SECURITY_IPSEC_TUNNEL_IPV4) &&
+	    (ipsec_xfrm->tunnel.type != RTE_SECURITY_IPSEC_TUNNEL_IPV6))
+		return -EINVAL;
+
+	if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD)
+		return ipsec_xform_aead_verify(ipsec_xfrm, crypto_xfrm);
+
+	return -ENOTSUP;
+}
+
+static uint64_t
+ipsec_cpt_inst_w7_get(struct roc_cpt *roc_cpt, void *sa)
+{
+	union cpt_inst_w7 w7;
+
+	w7.u64 = 0;
+	w7.s.egrp = roc_cpt->eng_grp[CPT_ENG_TYPE_IE];
+	w7.s.ctx_val = 1;
+	w7.s.cptr = (uint64_t)sa;
+	rte_mb();
+
+	return w7.u64;
+}
+
+static int
+ipsec_get_inb_ctx_size(struct roc_ot_ipsec_inb_sa *sa __rte_unused)
+{
+
+	return offsetof(struct roc_ot_ipsec_inb_sa, ctx) +
+	       offsetof(struct roc_ot_ipsec_inb_ctx_update_reg, ar_winbits) + 8;
+}
+
+static int
+ipsec_sa_inb_param_fill(struct roc_cpt *roc_cpt, struct cn10k_ipsec_sa *sa)
+{
+	/* TODO add support for antireplay */
+	sa->in_sa.w0.s.ar_win = 0;
+
+	/* TODO add support for udp encap */
+
+	sa->inst.w7 = ipsec_cpt_inst_w7_get(roc_cpt, sa);
+
+	return 0;
+}
+
+static int
+ipsec_sa_len_precalc(struct rte_security_ipsec_xform *ipsec,
+		     struct rte_crypto_sym_xform *xform,
+		     struct cn10k_ipsec_sa *sa)
+{
+	if (ipsec->tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV4)
+		sa->partial_len = sizeof(struct rte_ipv4_hdr);
+	else if (ipsec->tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV6)
+		sa->partial_len = sizeof(struct rte_ipv6_hdr);
+	else
+		return -EINVAL;
+
+	if (ipsec->proto == RTE_SECURITY_IPSEC_SA_PROTO_ESP) {
+		sa->partial_len += sizeof(struct rte_esp_hdr);
+		sa->roundup_len = sizeof(struct rte_esp_tail);
+	} else if (ipsec->proto == RTE_SECURITY_IPSEC_SA_PROTO_AH) {
+		sa->partial_len += ROC_IE_AH_HDR_LEN;
+	} else {
+		return -EINVAL;
+	}
+
+	if (ipsec->options.udp_encap)
+		sa->partial_len += sizeof(struct rte_udp_hdr);
+
+	if (xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
+		if (xform->aead.algo == RTE_CRYPTO_AEAD_AES_GCM) {
+			sa->partial_len += ROC_IE_AES_GCM_IV_LEN;
+			sa->partial_len += ROC_IE_AES_GCM_MAC_LEN;
+			sa->roundup_byte = ROC_IE_AES_GCM_ROUNDUP_BYTE_LEN;
+			return 0;
+		} else {
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int
+ipsec_sa_outb_param_fill(struct roc_cpt *roc_cpt,
+			 struct cn10k_ipsec_sa *ipsec_sa,
+			 struct rte_security_ipsec_xform *ipsec)
+{
+	struct roc_ot_ipsec_outb_sa *sa = &ipsec_sa->out_sa;
+	uint32_t *ip_addr;
+
+	/* Set up tunnel header generation */
+	if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
+		if (ipsec->tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
+			sa->w2.s.outer_ip_ver = ROC_IE_OT_SA_IP_VERSION_4;
+			memcpy(&sa->outer_hdr.ipv4.src_addr,
+			       &ipsec->tunnel.ipv4.src_ip,
+			       sizeof(struct in_addr));
+			ip_addr = (uint32_t *)&sa->outer_hdr.ipv4.src_addr;
+			*ip_addr = rte_be_to_cpu_32(*ip_addr);
+			memcpy(&sa->outer_hdr.ipv4.dst_addr,
+			       &ipsec->tunnel.ipv4.dst_ip,
+			       sizeof(struct in_addr));
+			ip_addr = (uint32_t *)&sa->outer_hdr.ipv4.dst_addr;
+			*ip_addr = rte_be_to_cpu_32(*ip_addr);
+
+			if (!ipsec->options.copy_df) {
+				sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
+					ROC_IE_OT_SA_COPY_FROM_SA;
+				sa->w10.s.ipv4_df_or_ipv6_flw_lbl =
+					ipsec->tunnel.ipv4.df;
+			} else
+				sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
+					ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
+
+			if (!ipsec->options.copy_dscp) {
+				sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_SA;
+				sa->w10.s.dscp = ipsec->tunnel.ipv4.dscp;
+			} else
+				sa->w2.s.dscp_src =
+					ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
+
+		} else if (ipsec->tunnel.type ==
+			   RTE_SECURITY_IPSEC_TUNNEL_IPV6) {
+			sa->w2.s.outer_ip_ver = ROC_IE_OT_SA_IP_VERSION_6;
+			memcpy(&sa->outer_hdr.ipv6.src_addr,
+			       &ipsec->tunnel.ipv6.src_addr,
+			       sizeof(struct in6_addr));
+			memcpy(&sa->outer_hdr.ipv6.dst_addr,
+			       &ipsec->tunnel.ipv6.dst_addr,
+			       sizeof(struct in6_addr));
+
+			if (!ipsec->options.copy_flabel) {
+				sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
+					ROC_IE_OT_SA_COPY_FROM_SA;
+
+				sa->w10.s.ipv4_df_or_ipv6_flw_lbl =
+					ipsec->tunnel.ipv6.flabel;
+			} else
+				sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
+					ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
+
+			if (!ipsec->options.copy_dscp) {
+				sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_SA;
+				sa->w10.s.dscp = ipsec->tunnel.ipv6.dscp;
+			} else
+				sa->w2.s.dscp_src =
+					ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
+		} else {
+			return -EINVAL;
+		}
+
+	} else {
+		return -EINVAL;
+	}
+
+	ipsec_sa->inst.w7 = ipsec_cpt_inst_w7_get(roc_cpt, sa);
+
+	return 0;
+}
+
+static void
+ipsec_sa_common_param_fill(union roc_ot_ipsec_sa_word2 *w2, uint8_t *cipher_key,
+			   uint8_t *salt_key,
+			   struct rte_security_ipsec_xform *ipsec_xfrm,
+			   struct rte_crypto_sym_xform *crypto_xfrm)
+{
+	const uint8_t *key = NULL;
+	uint32_t *tmp_salt;
+	uint64_t *tmp_key;
+	uint32_t i;
+	int length = 0;
+
+	/* Set direction */
+	if (ipsec_xfrm->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS)
+		w2->s.dir = ROC_IE_OT_SA_DIR_INBOUND;
+	else
+		w2->s.dir = ROC_IE_OT_SA_DIR_OUTBOUND;
+
+	/* Set protocol - ESP vs AH */
+	if (ipsec_xfrm->proto == RTE_SECURITY_IPSEC_SA_PROTO_ESP)
+		w2->s.protocol = ROC_IE_OT_SA_PROTOCOL_ESP;
+	else
+		w2->s.protocol = ROC_IE_OT_SA_PROTOCOL_AH;
+
+	/* Set mode - transport vs tunnel */
+	if (ipsec_xfrm->mode == RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT)
+		w2->s.mode = ROC_IE_OT_SA_MODE_TRANSPORT;
+	else
+		w2->s.mode = ROC_IE_OT_SA_MODE_TUNNEL;
+
+	/* Set encryption algorithm */
+	if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
+		switch ((int)crypto_xfrm->aead.algo) {
+		case RTE_CRYPTO_AEAD_AES_GCM:
+			w2->s.enc_type = ROC_IE_OT_SA_ENC_AES_GCM;
+			w2->s.auth_type = ROC_IE_OT_SA_AUTH_NULL;
+			memcpy(salt_key, &ipsec_xfrm->salt, ROC_SALT_LEN);
+			tmp_salt = (uint32_t *)salt_key;
+			*tmp_salt = rte_be_to_cpu_32(*tmp_salt);
+			break;
+		}
+		key = crypto_xfrm->aead.key.data;
+		length = crypto_xfrm->aead.key.length;
+	}
+
+	w2->s.spi = ipsec_xfrm->spi;
+
+	/* Copy encryption key */
+	memcpy(cipher_key, key, length);
+	tmp_key = (uint64_t *)cipher_key;
+	for (i = 0; i < ROC_CTX_MAX_CKEY_LEN / sizeof(uint64_t); i++)
+		tmp_key[i] = rte_be_to_cpu_64(tmp_key[i]);
+
+	switch (length) {
+	case ROC_AES128_KEY_LEN:
+		w2->s.aes_key_len = ROC_IE_OT_SA_AES_KEY_LEN_128;
+		break;
+	case ROC_AES192_KEY_LEN:
+		w2->s.aes_key_len = ROC_IE_OT_SA_AES_KEY_LEN_192;
+		break;
+	case ROC_AES256_KEY_LEN:
+		w2->s.aes_key_len = ROC_IE_OT_SA_AES_KEY_LEN_256;
+		break;
+	}
+}
+
+static int
+cn10k_ipsec_outb_sa_create(struct roc_cpt *roc_cpt,
+			   struct rte_security_ipsec_xform *ipsec_xfrm,
+			   struct rte_crypto_sym_xform *crypto_xfrm,
+			   struct rte_security_session *sec_sess)
+{
+	struct roc_ot_ipsec_outb_sa *out_sa;
+	struct cn10k_sec_session *sess;
+	struct cn10k_ipsec_sa *sa;
+	union cpt_inst_w4 inst_w4;
+	size_t offset;
+	int ret;
+
+	sess = get_sec_session_private_data(sec_sess);
+	sa = &sess->sa;
+	out_sa = &sa->out_sa;
+
+	memset(out_sa, 0, sizeof(struct roc_ot_ipsec_outb_sa));
+
+	ipsec_sa_common_param_fill((union roc_ot_ipsec_sa_word2 *)&out_sa->w2,
+				   out_sa->cipher_key, out_sa->iv.s.salt,
+				   ipsec_xfrm, crypto_xfrm);
+
+	ret = ipsec_sa_outb_param_fill(roc_cpt, sa, ipsec_xfrm);
+	if (ret)
+		return ret;
+
+	ret = ipsec_sa_len_precalc(ipsec_xfrm, crypto_xfrm, sa);
+	if (ret)
+		return ret;
+
+	/* Set context offsets and sizes */
+
+	/* Set offset of hw_ctx in 8b units */
+	offset = offsetof(struct roc_ot_ipsec_outb_sa, ctx);
+	out_sa->w0.s.hw_ctx_off = offset / ROC_CTX_UNIT_8B;
+
+	/* Context push size for outbound spans up to and includes
+	 * relevant keys, for example for AES-GCM it need not push beyond
+	 * cipher_key field, for SHAx it need not push beyond
+	 * hmac_opad_ipad field.
+	 * TODO for now let's set it up to hw_ctx however it should be
+	 * updated later
+	 */
+	out_sa->w0.s.ctx_push_size = out_sa->w0.s.hw_ctx_off;
+	/* Entire context size in 128b units */
+	offset = sizeof(struct roc_ot_ipsec_outb_sa);
+	out_sa->w0.s.ctx_size =
+		PLT_ALIGN_CEIL(offset, ROC_CTX_UNIT_128B) / ROC_CTX_UNIT_128B -
+		1;
+	/* There are 2 words prepended to the context */
+	out_sa->w0.s.ctx_hdr_size = CN10K_IPSEC_SA_CTX_HDR_SIZE;
+	out_sa->w0.s.aop_valid = 1;
+
+	/* pre-populate CPT INST word 4 */
+	inst_w4.u64 = 0;
+	inst_w4.s.opcode_major = ROC_IE_OT_MAJOR_OP_PROCESS_OUTBOUND_IPSEC;
+	inst_w4.s.param1 = 0;
+	sa->inst.w4 = inst_w4.u64;
+
+	out_sa->w2.s.ipid_gen = 1;
+
+	/* Enable SA */
+	out_sa->w2.s.valid = 1;
+
+	return 0;
+}
+
+static int
+cn10k_ipsec_inb_sa_create(struct roc_cpt *roc_cpt,
+			  struct rte_security_ipsec_xform *ipsec_xfrm,
+			  struct rte_crypto_sym_xform *crypto_xfrm,
+			  struct rte_security_session *sec_sess)
+{
+	struct roc_ot_ipsec_inb_sa *in_sa;
+	struct cn10k_sec_session *sess;
+	struct cn10k_ipsec_sa *sa;
+	union cpt_inst_w4 inst_w4;
+	size_t offset;
+
+	sess = get_sec_session_private_data(sec_sess);
+	sa = &sess->sa;
+	in_sa = &sa->in_sa;
+
+	ipsec_sa_common_param_fill((union roc_ot_ipsec_sa_word2 *)&in_sa->w2,
+				   in_sa->cipher_key, in_sa->w8.s.salt,
+				   ipsec_xfrm, crypto_xfrm);
+
+	ipsec_sa_inb_param_fill(roc_cpt, sa);
+
+	/* Set context offsets and sizes */
+
+	/* Set offset of hw_ctx in 8b units */
+	offset = offsetof(struct roc_ot_ipsec_inb_sa, ctx);
+	in_sa->w0.s.hw_ctx_off = offset / ROC_CTX_UNIT_8B;
+
+	/* Context push size for inbound spans up to hw_ctx including ar_base
+	 * field, in 8b units
+	 */
+	in_sa->w0.s.ctx_push_size = in_sa->w0.s.hw_ctx_off + 1;
+	/* Entire context size in 128b units */
+	in_sa->w0.s.ctx_size = PLT_ALIGN_CEIL(ipsec_get_inb_ctx_size(in_sa),
+					      ROC_CTX_UNIT_128B) /
+				       ROC_CTX_UNIT_128B -
+			       1;
+	/* There are 2 words prepended to the context */
+	in_sa->w0.s.ctx_hdr_size = CN10K_IPSEC_SA_CTX_HDR_SIZE;
+	in_sa->w0.s.aop_valid = 1;
+
+	/* pre-populate CPT INST word 4 */
+	inst_w4.u64 = 0;
+	inst_w4.s.opcode_major = ROC_IE_OT_MAJOR_OP_PROCESS_INBOUND_IPSEC;
+
+	/* Disable checksum verification for now */
+	inst_w4.s.param1 = 7;
+	sa->inst.w4 = inst_w4.u64;
+
+	in_sa->w2.s.outer_ip_ver = ROC_IE_OT_SA_IP_VERSION_4;
+
+	/* Enable SA */
+	in_sa->w2.s.valid = 1;
+
+	return 0;
+}
+
+static int
+cn10k_ipsec_session_create(void *dev,
+			   struct rte_security_ipsec_xform *ipsec_xfrm,
+			   struct rte_crypto_sym_xform *crypto_xfrm,
+			   struct rte_security_session *sess)
+{
+	struct rte_cryptodev *crypto_dev = dev;
+	struct roc_cpt *roc_cpt;
+	struct cnxk_cpt_vf *vf;
+	int ret;
+
+	vf = crypto_dev->data->dev_private;
+	roc_cpt = &vf->cpt;
+
+	if (crypto_dev->data->queue_pairs[0] == NULL) {
+		plt_err("Setup cpt queue pair before creating security session");
+		return -EPERM;
+	}
+
+	ret = cn10k_ipsec_xform_verify(ipsec_xfrm, crypto_xfrm);
+	if (ret)
+		return ret;
+
+	if (ipsec_xfrm->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS)
+		return cn10k_ipsec_inb_sa_create(roc_cpt, ipsec_xfrm,
+						 crypto_xfrm, sess);
+	else
+		return cn10k_ipsec_outb_sa_create(roc_cpt, ipsec_xfrm,
+						  crypto_xfrm, sess);
+}
+
+static int
+cn10k_sec_session_create(void *device, struct rte_security_session_conf *conf,
+			 struct rte_security_session *sess,
+			 struct rte_mempool *mempool)
+{
+	struct cn10k_sec_session *priv;
+	int ret;
+
+	if (conf->action_type != RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL)
+		return -EINVAL;
+
+	if (rte_security_dynfield_register() < 0)
+		return -ENOTSUP;
+
+	if (rte_mempool_get(mempool, (void **)&priv)) {
+		plt_err("Could not allocate security session private data");
+		return -ENOMEM;
+	}
+
+	set_sec_session_private_data(sess, priv);
+
+	priv->userdata = conf->userdata;
+
+	if (conf->protocol != RTE_SECURITY_PROTOCOL_IPSEC) {
+		ret = -ENOTSUP;
+		goto mempool_put;
+	}
+	ret = cn10k_ipsec_session_create(device, &conf->ipsec,
+					 conf->crypto_xform, sess);
+	if (ret)
+		goto mempool_put;
+
+	return 0;
+
+mempool_put:
+	rte_mempool_put(mempool, priv);
+	set_sec_session_private_data(sess, NULL);
+	return ret;
+}
+
+static int
+cn10k_sec_session_destroy(void *device __rte_unused,
+			  struct rte_security_session *sess)
+{
+	struct cn10k_sec_session *priv;
+	struct rte_mempool *sess_mp;
+
+	priv = get_sec_session_private_data(sess);
+
+	if (priv == NULL)
+		return 0;
+
+	sess_mp = rte_mempool_from_obj(priv);
+
+	set_sec_session_private_data(sess, NULL);
+	rte_mempool_put(sess_mp, priv);
+
+	return 0;
+}
+
+static unsigned int
+cn10k_sec_session_get_size(void *device __rte_unused)
+{
+	return sizeof(struct cn10k_sec_session);
+}
+
+/* Update platform specific security ops */
+void
+cn10k_sec_ops_override(void)
+{
+	/* Update platform specific ops */
+	cnxk_sec_ops.session_create = cn10k_sec_session_create;
+	cnxk_sec_ops.session_destroy = cn10k_sec_session_destroy;
+	cnxk_sec_ops.session_get_size = cn10k_sec_session_get_size;
+}
diff --git a/drivers/crypto/cnxk/cn10k_ipsec.h b/drivers/crypto/cnxk/cn10k_ipsec.h
new file mode 100644
index 0000000..6e36e67
--- /dev/null
+++ b/drivers/crypto/cnxk/cn10k_ipsec.h
@@ -0,0 +1,38 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+
+#ifndef __CN10K_IPSEC_H__
+#define __CN10K_IPSEC_H__
+
+#include <rte_security.h>
+
+#include "roc_platform.h"
+#include "roc_ie_ot.h"
+#include "cnxk_ipsec.h"
+
+#define CN10K_IPSEC_SA_CTX_HDR_SIZE 1
+
+struct cn10k_ipsec_sa {
+	union {
+		/** Inbound SA */
+		struct roc_ot_ipsec_inb_sa in_sa;
+		/** Outbound SA */
+		struct roc_ot_ipsec_outb_sa out_sa;
+	};
+	/** Pre-populated CPT inst words */
+	struct cnxk_cpt_inst_tmpl inst;
+	uint8_t partial_len;
+	uint8_t roundup_len;
+	uint8_t roundup_byte;
+};
+
+struct cn10k_sec_session {
+	struct cn10k_ipsec_sa sa;
+	void *userdata;
+	/**< Userdata registered by the application */
+} __rte_cache_aligned;
+
+void cn10k_sec_ops_override(void);
+
+#endif /* __CN10K_IPSEC_H__ */
diff --git a/drivers/crypto/cnxk/cnxk_ipsec.h b/drivers/crypto/cnxk/cnxk_ipsec.h
new file mode 100644
index 0000000..8b9500d
--- /dev/null
+++ b/drivers/crypto/cnxk/cnxk_ipsec.h
@@ -0,0 +1,18 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+#ifndef __CNXK_IPSEC_H__
+#define __CNXK_IPSEC_H__
+
+#include <rte_security.h>
+#include <rte_security_driver.h>
+
+extern struct rte_security_ops cnxk_sec_ops;
+
+struct cnxk_cpt_inst_tmpl {
+	uint64_t w2;
+	uint64_t w4;
+	uint64_t w7;
+};
+
+#endif /* __CNXK_IPSEC_H__ */
diff --git a/drivers/crypto/cnxk/meson.build b/drivers/crypto/cnxk/meson.build
index ab45483..eea08fa 100644
--- a/drivers/crypto/cnxk/meson.build
+++ b/drivers/crypto/cnxk/meson.build
@@ -13,6 +13,7 @@  sources = files(
         'cn9k_cryptodev_ops.c',
         'cn10k_cryptodev.c',
         'cn10k_cryptodev_ops.c',
+        'cn10k_ipsec.c',
         'cnxk_cpt_ops_helper.c',
         'cnxk_cryptodev.c',
         'cnxk_cryptodev_capabilities.c',
@@ -20,4 +21,4 @@  sources = files(
         'cnxk_cryptodev_sec.c',
 )
 
-deps += ['bus_pci', 'common_cnxk', 'security']
+deps += ['bus_pci', 'common_cnxk', 'security', 'rte_net']