diff mbox series

[21.11,1/3] test/crypto: add lookaside IPsec tests

Message ID 1627555402-4789-2-git-send-email-anoobj@marvell.com (mailing list archive)
State Superseded, archived
Delegated to: akhil goyal
Headers show
Series Add lookaside IPsec tests | expand

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Anoob Joseph July 29, 2021, 10:43 a.m. UTC
Added test case for lookaside IPsec. Following tests are added,

1. Inbound known vector [AES-GCM 128, 192 & 256]
2. Outbound known vector [AES-GCM 128, 192 & 256]

Signed-off-by: Anoob Joseph <anoobj@marvell.com>
Signed-off-by: Tejasree Kondoj <ktejasree@marvell.com>
---
 app/test/meson.build                               |   1 +
 app/test/test.h                                    |   6 +
 app/test/test_cryptodev.c                          | 250 ++++++++++++++++
 app/test/test_cryptodev_security_ipsec.c           | 202 +++++++++++++
 app/test/test_cryptodev_security_ipsec.h           |  66 +++++
 .../test_cryptodev_security_ipsec_test_vectors.h   | 321 +++++++++++++++++++++
 6 files changed, 846 insertions(+)
 create mode 100644 app/test/test_cryptodev_security_ipsec.c
 create mode 100644 app/test/test_cryptodev_security_ipsec.h
 create mode 100644 app/test/test_cryptodev_security_ipsec_test_vectors.h
diff mbox series

Patch

diff --git a/app/test/meson.build b/app/test/meson.build
index 88aae44..4cfa022 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -31,6 +31,7 @@  test_sources = files(
         'test_cryptodev.c',
         'test_cryptodev_asym.c',
         'test_cryptodev_blockcipher.c',
+        'test_cryptodev_security_ipsec.c',
         'test_cryptodev_security_pdcp.c',
         'test_cycles.c',
         'test_debug.c',
diff --git a/app/test/test.h b/app/test/test.h
index c3b2a87..7115edf 100644
--- a/app/test/test.h
+++ b/app/test/test.h
@@ -124,6 +124,12 @@  struct unit_test_case {
 #define TEST_CASE_WITH_DATA(setup, teardown, testcase, data) \
 		{ setup, teardown, NULL, testcase, #testcase, 1, data }
 
+#define TEST_CASE_NAMED_ST(name, setup, teardown, testcase) \
+		{ setup, teardown, NULL, testcase, name, 1, NULL }
+
+#define TEST_CASE_NAMED_WITH_DATA(name, setup, teardown, testcase, data) \
+		{ setup, teardown, NULL, testcase, name, 1, data }
+
 #define TEST_CASE_DISABLED(fn) { NULL, NULL, fn, NULL, #fn, 0, NULL }
 
 #define TEST_CASE_ST_DISABLED(setup, teardown, testcase) \
diff --git a/app/test/test_cryptodev.c b/app/test/test_cryptodev.c
index ead8c6e..6e5bd69 100644
--- a/app/test/test_cryptodev.c
+++ b/app/test/test_cryptodev.c
@@ -17,6 +17,7 @@ 
 #include <rte_crypto.h>
 #include <rte_cryptodev.h>
 #include <rte_cryptodev_pmd.h>
+#include <rte_ip.h>
 #include <rte_string_fns.h>
 
 #ifdef RTE_CRYPTO_SCHEDULER
@@ -42,6 +43,8 @@ 
 #include "test_cryptodev_hmac_test_vectors.h"
 #include "test_cryptodev_mixed_test_vectors.h"
 #ifdef RTE_LIB_SECURITY
+#include "test_cryptodev_security_ipsec.h"
+#include "test_cryptodev_security_ipsec_test_vectors.h"
 #include "test_cryptodev_security_pdcp_test_vectors.h"
 #include "test_cryptodev_security_pdcp_sdap_test_vectors.h"
 #include "test_cryptodev_security_pdcp_test_func.h"
@@ -128,6 +131,13 @@  test_AES_CBC_HMAC_SHA512_decrypt_perform(struct rte_cryptodev_sym_session *sess,
 		const uint8_t *digest,
 		const uint8_t *iv);
 
+static int
+security_proto_supported(enum rte_security_session_action_type action,
+	enum rte_security_session_protocol proto);
+
+static int
+dev_configure_and_start(uint64_t ff_disable);
+
 static struct rte_mbuf *
 setup_test_string(struct rte_mempool *mpool,
 		const char *string, size_t len, uint8_t blocksize)
@@ -757,6 +767,42 @@  crypto_gen_testsuite_setup(void)
 
 #ifdef RTE_LIB_SECURITY
 static int
+ipsec_proto_testsuite_setup(void)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_SECURITY)) {
+		RTE_LOG(INFO, USER1, "Feature flag requirements for IPsec Proto "
+				"testsuite not met\n");
+		return TEST_SKIPPED;
+	}
+
+	/* Reconfigure to enable security */
+	dev_configure_and_start(RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+				RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO);
+
+	/* Set action type */
+	ut_params->type = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+
+	if (security_proto_supported(
+			RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+			RTE_SECURITY_PROTOCOL_IPSEC) < 0) {
+		RTE_LOG(INFO, USER1, "Capability requirements for IPsec Proto "
+				"test not met\n");
+		return TEST_SKIPPED;
+	}
+
+	/* Stop the device */
+	rte_cryptodev_stop(ts_params->valid_devs[0]);
+
+	return 0;
+}
+
+static int
 pdcp_proto_testsuite_setup(void)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -8814,6 +8860,177 @@  test_PDCP_SDAP_PROTO_decap_all(void)
 }
 
 static int
+test_ipsec_proto_process(const struct ipsec_test_data td[],
+			 struct ipsec_test_data res_d[],
+			 int nb_td,
+			 bool silent)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+	struct rte_security_capability_idx sec_cap_idx;
+	const struct rte_security_capability *sec_cap;
+	struct rte_security_ipsec_xform ipsec_xform;
+	uint8_t dev_id = ts_params->valid_devs[0];
+	enum rte_security_ipsec_sa_direction dir;
+	uint32_t src = RTE_IPV4(192, 168, 1, 0);
+	uint32_t dst = RTE_IPV4(192, 168, 1, 1);
+	int salt_len, i, ret = TEST_SUCCESS;
+	struct rte_security_ctx *ctx;
+	uint8_t *input_text;
+
+	ut_params->type = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+	gbl_action_type = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+
+	/* Use first test data to create session */
+
+	/* Copy IPsec xform */
+	memcpy(&ipsec_xform, &td[0].ipsec_xform, sizeof(ipsec_xform));
+
+	memcpy(&ipsec_xform.tunnel.ipv4.src_ip, &src, sizeof(src));
+	memcpy(&ipsec_xform.tunnel.ipv4.dst_ip, &dst, sizeof(dst));
+
+	dir = ipsec_xform.direction;
+
+	ctx = rte_cryptodev_get_sec_ctx(dev_id);
+
+	sec_cap_idx.action = ut_params->type;
+	sec_cap_idx.protocol = RTE_SECURITY_PROTOCOL_IPSEC;
+	sec_cap_idx.ipsec.proto = ipsec_xform.proto;
+	sec_cap_idx.ipsec.mode = ipsec_xform.mode;
+	sec_cap_idx.ipsec.direction = ipsec_xform.direction;
+
+	sec_cap = rte_security_capability_get(ctx, &sec_cap_idx);
+	if (sec_cap == NULL)
+		return TEST_SKIPPED;
+
+	/* Copy cipher session parameters */
+	if (td[0].aead) {
+		memcpy(&ut_params->aead_xform, &td[0].xform.aead,
+		       sizeof(ut_params->aead_xform));
+		ut_params->aead_xform.aead.key.data = td[0].key.data;
+		ut_params->aead_xform.aead.iv.offset = IV_OFFSET;
+
+		/* Verify crypto capabilities */
+		if (test_ipsec_crypto_caps_aead_verify(
+				sec_cap,
+				&ut_params->aead_xform) != 0) {
+			if (!silent)
+				RTE_LOG(INFO, USER1,
+					"Crypto capabilities not supported\n");
+			return TEST_SKIPPED;
+		}
+	} else {
+		/* Only AEAD supported now */
+		return TEST_SKIPPED;
+	}
+
+	if (test_ipsec_sec_caps_verify(&ipsec_xform, sec_cap, silent) != 0)
+		return TEST_SKIPPED;
+
+	salt_len = RTE_MIN(sizeof(ipsec_xform.salt), td[0].salt.len);
+	memcpy(&ipsec_xform.salt, td[0].salt.data, salt_len);
+
+	struct rte_security_session_conf sess_conf = {
+		.action_type = ut_params->type,
+		.protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+		.ipsec = ipsec_xform,
+		.crypto_xform = &ut_params->aead_xform,
+	};
+
+	/* Create security session */
+	ut_params->sec_session = rte_security_session_create(ctx, &sess_conf,
+					ts_params->session_mpool,
+					ts_params->session_priv_mpool);
+
+	if (ut_params->sec_session == NULL)
+		return TEST_SKIPPED;
+
+	for (i = 0; i < nb_td; i++) {
+		/* Setup source mbuf payload */
+		ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+		memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+				rte_pktmbuf_tailroom(ut_params->ibuf));
+
+		input_text = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+				td[i].input_text.len);
+
+		memcpy(input_text, td[i].input_text.data,
+		       td[i].input_text.len);
+
+		/* Generate crypto op data structure */
+		ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+					RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+		if (!ut_params->op) {
+			printf("TestCase %s line %d: %s\n",
+				__func__, __LINE__,
+				"failed to allocate crypto op");
+			ret = TEST_FAILED;
+			goto crypto_op_free;
+		}
+
+		/* Attach session to operation */
+		rte_security_attach_session(ut_params->op,
+					    ut_params->sec_session);
+
+		/* Set crypto operation mbufs */
+		ut_params->op->sym->m_src = ut_params->ibuf;
+		ut_params->op->sym->m_dst = NULL;
+
+		/* Copy IV at the end of the crypto operation for egress */
+		if (dir == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
+			rte_memcpy(rte_crypto_op_ctod_offset(ut_params->op,
+				   uint8_t *, IV_OFFSET),
+				   td[i].iv.data,
+				   td[i].xform.aead.aead.iv.length);
+
+		/* Process crypto operation */
+		process_crypto_request(dev_id, ut_params->op);
+
+		ret = test_ipsec_status_check(ut_params->op, dir);
+		if (ret != TEST_SUCCESS)
+			goto crypto_op_free;
+
+		ret = test_ipsec_post_process(ut_params->ibuf, &td[i],
+					      &res_d[i], silent);
+
+		rte_crypto_op_free(ut_params->op);
+		ut_params->op = NULL;
+
+		rte_pktmbuf_free(ut_params->ibuf);
+		ut_params->ibuf = NULL;
+	}
+
+crypto_op_free:
+	rte_crypto_op_free(ut_params->op);
+	ut_params->op = NULL;
+
+	rte_pktmbuf_free(ut_params->ibuf);
+	ut_params->ibuf = NULL;
+
+	if (ut_params->sec_session)
+		rte_security_session_destroy(ctx, ut_params->sec_session);
+	ut_params->sec_session = NULL;
+
+	return ret;
+}
+
+static int
+test_ipsec_proto_known_vec(const void *test_data)
+{
+	return test_ipsec_proto_process(test_data, NULL, 1, false);
+}
+
+static int
+test_ipsec_proto_known_vec_inb(const void *td_outb)
+{
+	struct ipsec_test_data td_inb;
+
+	test_ipsec_td_in_from_out(td_outb, &td_inb);
+
+	return test_ipsec_proto_process(&td_inb, NULL, 1, false);
+}
+
+static int
 test_PDCP_PROTO_all(void)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -13703,6 +13920,38 @@  static struct unit_test_suite end_testsuite = {
 };
 
 #ifdef RTE_LIB_SECURITY
+static struct unit_test_suite ipsec_proto_testsuite  = {
+	.suite_name = "IPsec Proto Unit Test Suite",
+	.setup = ipsec_proto_testsuite_setup,
+	.unit_test_cases = {
+		TEST_CASE_NAMED_WITH_DATA(
+			"Outbound known vector (ESP tunnel mode IPv4 AES-GCM 128)",
+			ut_setup_security, ut_teardown,
+			test_ipsec_proto_known_vec, &pkt_aes_128_gcm),
+		TEST_CASE_NAMED_WITH_DATA(
+			"Outbound known vector (ESP tunnel mode IPv4 AES-GCM 192)",
+			ut_setup_security, ut_teardown,
+			test_ipsec_proto_known_vec, &pkt_aes_192_gcm),
+		TEST_CASE_NAMED_WITH_DATA(
+			"Outbound known vector (ESP tunnel mode IPv4 AES-GCM 256)",
+			ut_setup_security, ut_teardown,
+			test_ipsec_proto_known_vec, &pkt_aes_256_gcm),
+		TEST_CASE_NAMED_WITH_DATA(
+			"Inbound known vector (ESP tunnel mode IPv4 AES-GCM 128)",
+			ut_setup_security, ut_teardown,
+			test_ipsec_proto_known_vec_inb, &pkt_aes_128_gcm),
+		TEST_CASE_NAMED_WITH_DATA(
+			"Inbound known vector (ESP tunnel mode IPv4 AES-GCM 192)",
+			ut_setup_security, ut_teardown,
+			test_ipsec_proto_known_vec_inb, &pkt_aes_192_gcm),
+		TEST_CASE_NAMED_WITH_DATA(
+			"Inbound known vector (ESP tunnel mode IPv4 AES-GCM 256)",
+			ut_setup_security, ut_teardown,
+			test_ipsec_proto_known_vec_inb, &pkt_aes_256_gcm),
+		TEST_CASES_END() /**< NULL terminate unit test array */
+	}
+};
+
 static struct unit_test_suite pdcp_proto_testsuite  = {
 	.suite_name = "PDCP Proto Unit Test Suite",
 	.setup = pdcp_proto_testsuite_setup,
@@ -14489,6 +14738,7 @@  run_cryptodev_testsuite(const char *pmd_name)
 		&cryptodev_negative_hmac_sha1_testsuite,
 		&cryptodev_gen_testsuite,
 #ifdef RTE_LIB_SECURITY
+		&ipsec_proto_testsuite,
 		&pdcp_proto_testsuite,
 		&docsis_proto_testsuite,
 #endif
diff --git a/app/test/test_cryptodev_security_ipsec.c b/app/test/test_cryptodev_security_ipsec.c
new file mode 100644
index 0000000..789d39c
--- /dev/null
+++ b/app/test/test_cryptodev_security_ipsec.c
@@ -0,0 +1,202 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+
+#include <rte_common.h>
+#include <rte_cryptodev.h>
+#include <rte_ip.h>
+#include <rte_security.h>
+
+#include "test.h"
+#include "test_cryptodev_security_ipsec.h"
+
+int
+test_ipsec_sec_caps_verify(struct rte_security_ipsec_xform *ipsec_xform,
+			   const struct rte_security_capability *sec_cap,
+			   bool silent)
+{
+	/* Verify security capabilities */
+
+	if (ipsec_xform->options.esn == 1 && sec_cap->ipsec.options.esn == 0) {
+		if (!silent)
+			RTE_LOG(INFO, USER1, "ESN is not supported\n");
+		return -ENOTSUP;
+	}
+
+	if (ipsec_xform->options.udp_encap == 1 &&
+	    sec_cap->ipsec.options.udp_encap == 0) {
+		if (!silent)
+			RTE_LOG(INFO, USER1, "UDP encapsulation is not supported\n");
+		return -ENOTSUP;
+	}
+
+	if (ipsec_xform->options.copy_dscp == 1 &&
+	    sec_cap->ipsec.options.copy_dscp == 0) {
+		if (!silent)
+			RTE_LOG(INFO, USER1, "Copy DSCP is not supported\n");
+		return -ENOTSUP;
+	}
+
+	if (ipsec_xform->options.copy_flabel == 1 &&
+	    sec_cap->ipsec.options.copy_flabel == 0) {
+		if (!silent)
+			RTE_LOG(INFO, USER1, "Copy Flow Label is not supported\n");
+		return -ENOTSUP;
+	}
+
+	if (ipsec_xform->options.copy_df == 1 &&
+	    sec_cap->ipsec.options.copy_df == 0) {
+		if (!silent)
+			RTE_LOG(INFO, USER1, "Copy DP bit is not supported\n");
+		return -ENOTSUP;
+	}
+
+	if (ipsec_xform->options.dec_ttl == 1 &&
+	    sec_cap->ipsec.options.dec_ttl == 0) {
+		if (!silent)
+			RTE_LOG(INFO, USER1, "Decrement TTL is not supported\n");
+		return -ENOTSUP;
+	}
+
+	if (ipsec_xform->options.ecn == 1 && sec_cap->ipsec.options.ecn == 0) {
+		if (!silent)
+			RTE_LOG(INFO, USER1, "ECN is not supported\n");
+		return -ENOTSUP;
+	}
+
+	if (ipsec_xform->options.stats == 1 &&
+	    sec_cap->ipsec.options.stats == 0) {
+		if (!silent)
+			RTE_LOG(INFO, USER1, "Stats is not supported\n");
+		return -ENOTSUP;
+	}
+
+	return 0;
+}
+
+int
+test_ipsec_crypto_caps_aead_verify(
+		const struct rte_security_capability *sec_cap,
+		struct rte_crypto_sym_xform *aead)
+{
+	const struct rte_cryptodev_symmetric_capability *sym_cap;
+	const struct rte_cryptodev_capabilities *crypto_cap;
+	int j = 0;
+
+	while ((crypto_cap = &sec_cap->crypto_capabilities[j++])->op !=
+			RTE_CRYPTO_OP_TYPE_UNDEFINED) {
+		if (crypto_cap->op == RTE_CRYPTO_OP_TYPE_SYMMETRIC &&
+				crypto_cap->sym.xform_type == aead->type &&
+				crypto_cap->sym.aead.algo == aead->aead.algo) {
+			sym_cap = &crypto_cap->sym;
+			if (rte_cryptodev_sym_capability_check_aead(sym_cap,
+					aead->aead.key.length,
+					aead->aead.digest_length,
+					aead->aead.aad_length,
+					aead->aead.iv.length) == 0)
+				return 0;
+		}
+	}
+
+	return -ENOTSUP;
+}
+
+void
+test_ipsec_td_in_from_out(const struct ipsec_test_data *td_out,
+			  struct ipsec_test_data *td_in)
+{
+	memcpy(td_in, td_out, sizeof(*td_in));
+
+	/* Populate output text of td_in with input text of td_out */
+	memcpy(td_in->output_text.data, td_out->input_text.data,
+	       td_out->input_text.len);
+	td_in->output_text.len = td_out->input_text.len;
+
+	/* Populate input text of td_in with output text of td_out */
+	memcpy(td_in->input_text.data, td_out->output_text.data,
+	       td_out->output_text.len);
+	td_in->input_text.len = td_out->output_text.len;
+
+	td_in->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
+
+	if (td_in->aead) {
+		td_in->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT;
+	} else {
+		td_in->xform.chain.auth.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
+		td_in->xform.chain.cipher.cipher.op =
+				RTE_CRYPTO_CIPHER_OP_DECRYPT;
+	}
+}
+
+static int
+test_ipsec_td_verify(struct rte_mbuf *m, const struct ipsec_test_data *td,
+		     bool silent)
+{
+	uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *);
+	uint32_t skip = 0, len = rte_pktmbuf_pkt_len(m);
+
+	if (len != td->output_text.len) {
+		printf("Output length (%d) not matching with expected (%d)\n",
+			len, td->output_text.len);
+		return TEST_FAILED;
+	}
+
+	if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
+		if (td->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
+			if (td->ipsec_xform.tunnel.type ==
+					RTE_SECURITY_IPSEC_TUNNEL_IPV4)
+				skip += sizeof(struct rte_ipv4_hdr);
+			else
+				skip += sizeof(struct rte_ipv6_hdr);
+		}
+	}
+
+	len -= skip;
+	output_text += skip;
+
+	if (memcmp(output_text, td->output_text.data + skip, len)) {
+		if (silent)
+			return TEST_FAILED;
+
+		printf("TestCase %s line %d: %s\n", __func__, __LINE__,
+			"output text not as expected\n");
+
+		rte_hexdump(stdout, "expected", td->output_text.data + skip,
+			    len);
+		rte_hexdump(stdout, "actual", output_text, len);
+		return TEST_FAILED;
+	}
+
+	return TEST_SUCCESS;
+}
+
+int
+test_ipsec_post_process(struct rte_mbuf *m, const struct ipsec_test_data *td,
+			struct ipsec_test_data *res_d, bool silent)
+{
+	/*
+	 * In case of known vector tests & all inbound tests, res_d provided
+	 * would be NULL and output data need to be validated against expected.
+	 * For inbound, output_text would be plain packet and for outbound
+	 * output_text would IPsec packet. Validate by comparing against
+	 * known vectors.
+	 */
+	RTE_SET_USED(res_d);
+	return test_ipsec_td_verify(m, td, silent);
+}
+
+int
+test_ipsec_status_check(struct rte_crypto_op *op,
+			enum rte_security_ipsec_sa_direction dir)
+{
+	int ret = TEST_SUCCESS;
+
+	if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
+		printf("Security op processing failed\n");
+		ret = TEST_FAILED;
+	}
+
+	RTE_SET_USED(dir);
+
+	return ret;
+}
diff --git a/app/test/test_cryptodev_security_ipsec.h b/app/test/test_cryptodev_security_ipsec.h
new file mode 100644
index 0000000..5f1b46d
--- /dev/null
+++ b/app/test/test_cryptodev_security_ipsec.h
@@ -0,0 +1,66 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+
+#ifndef _TEST_CRYPTODEV_SECURITY_IPSEC_H_
+#define _TEST_CRYPTODEV_SECURITY_IPSEC_H_
+
+#include <rte_cryptodev.h>
+#include <rte_security.h>
+
+struct ipsec_test_data {
+	struct {
+		uint8_t data[32];
+	} key;
+
+	struct {
+		uint8_t data[1024];
+		unsigned int len;
+	} input_text;
+
+	struct {
+		uint8_t data[1024];
+		unsigned int len;
+	} output_text;
+
+	struct {
+		uint8_t data[4];
+		unsigned int len;
+	} salt;
+
+	struct {
+		uint8_t data[16];
+	} iv;
+
+	struct rte_security_ipsec_xform ipsec_xform;
+
+	bool aead;
+
+	union {
+		struct {
+			struct rte_crypto_sym_xform cipher;
+			struct rte_crypto_sym_xform auth;
+		} chain;
+		struct rte_crypto_sym_xform aead;
+	} xform;
+};
+
+int test_ipsec_sec_caps_verify(struct rte_security_ipsec_xform *ipsec_xform,
+			       const struct rte_security_capability *sec_cap,
+			       bool silent);
+
+int test_ipsec_crypto_caps_aead_verify(
+		const struct rte_security_capability *sec_cap,
+		struct rte_crypto_sym_xform *aead);
+
+void test_ipsec_td_in_from_out(const struct ipsec_test_data *td_out,
+			       struct ipsec_test_data *td_in);
+
+int test_ipsec_post_process(struct rte_mbuf *m,
+			    const struct ipsec_test_data *td,
+			    struct ipsec_test_data *res_d, bool silent);
+
+int test_ipsec_status_check(struct rte_crypto_op *op,
+			    enum rte_security_ipsec_sa_direction dir);
+
+#endif
diff --git a/app/test/test_cryptodev_security_ipsec_test_vectors.h b/app/test/test_cryptodev_security_ipsec_test_vectors.h
new file mode 100644
index 0000000..ae9cd24
--- /dev/null
+++ b/app/test/test_cryptodev_security_ipsec_test_vectors.h
@@ -0,0 +1,321 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Marvell
+ */
+
+#ifndef TEST_CRYPTODEV_SECURITY_IPSEC_TEST_VECTORS_H_
+#define TEST_CRYPTODEV_SECURITY_IPSEC_TEST_VECTORS_H_
+
+#include <rte_crypto.h>
+#include <rte_security.h>
+
+#include "test_cryptodev_security_ipsec.h"
+
+/*
+ * Known vectors
+ *
+ * AES-GCM vectors are based on :
+ * https://datatracker.ietf.org/doc/html/draft-mcgrew-gcm-test-01
+ *
+ * Vectors are updated to have corrected L4 checksum and sequence number 1.
+ */
+
+struct ipsec_test_data pkt_aes_128_gcm = {
+	.key = {
+		.data = {
+			0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+			0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
+		},
+	},
+	.input_text = {
+		.data = {
+			/* IP */
+			0x45, 0x00, 0x00, 0x3e, 0x69, 0x8f, 0x00, 0x00,
+			0x80, 0x11, 0x4d, 0xcc, 0xc0, 0xa8, 0x01, 0x02,
+			0xc0, 0xa8, 0x01, 0x01,
+
+			/* UDP */
+			0x0a, 0x98, 0x00, 0x35, 0x00, 0x2a, 0x23, 0x43,
+			0xb2, 0xd0, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x03, 0x73, 0x69, 0x70,
+			0x09, 0x63, 0x79, 0x62, 0x65, 0x72, 0x63, 0x69,
+			0x74, 0x79, 0x02, 0x64, 0x6b, 0x00, 0x00, 0x01,
+			0x00, 0x01,
+		},
+		.len = 62,
+	},
+	.output_text = {
+		.data = {
+			/* IP - outer header */
+			0x45, 0x00, 0x00, 0x74, 0x69, 0x8f, 0x00, 0x00,
+			0x80, 0x32, 0x4d, 0x75, 0xc0, 0xa8, 0x01, 0x02,
+			0xc0, 0xa8, 0x01, 0x01,
+
+			/* ESP */
+			0x00, 0x00, 0xa5, 0xf8, 0x00, 0x00, 0x00, 0x01,
+
+			/* IV */
+			0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
+
+			/* Data */
+			0xde, 0xb2, 0x2c, 0xd9, 0xb0, 0x7c, 0x72, 0xc1,
+			0x6e, 0x3a, 0x65, 0xbe, 0xeb, 0x8d, 0xf3, 0x04,
+			0xa5, 0xa5, 0x89, 0x7d, 0x33, 0xae, 0x53, 0x0f,
+			0x1b, 0xa7, 0x6d, 0x5d, 0x11, 0x4d, 0x2a, 0x5c,
+			0x3d, 0xe8, 0x18, 0x27, 0xc1, 0x0e, 0x9a, 0x4f,
+			0x51, 0x33, 0x0d, 0x0e, 0xec, 0x41, 0x66, 0x42,
+			0xcf, 0xbb, 0x85, 0xa5, 0xb4, 0x7e, 0x48, 0xa4,
+			0xec, 0x3b, 0x9b, 0xa9, 0x5d, 0x91, 0x8b, 0xd4,
+			0x29, 0xc7, 0x37, 0x57, 0x9f, 0xf1, 0x9e, 0x58,
+			0xcf, 0xfc, 0x60, 0x7a, 0x3b, 0xce, 0x89, 0x94,
+
+		},
+		.len = 116,
+	},
+	.salt = {
+		.data = {
+			0xca, 0xfe, 0xba, 0xbe
+		},
+		.len = 4,
+	},
+
+	.iv = {
+		.data = {
+			0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88
+		},
+	},
+
+	.ipsec_xform = {
+		.spi = 0xa5f8,
+		.options.esn = 0,
+		.options.udp_encap = 0,
+		.options.copy_dscp = 0,
+		.options.copy_flabel = 0,
+		.options.copy_df = 0,
+		.options.dec_ttl = 0,
+		.options.ecn = 0,
+		.options.stats = 0,
+		.direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
+		.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+		.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+		.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4,
+		.esn_soft_limit = 0,
+		.replay_win_sz = 0,
+	},
+
+	.aead = true,
+
+	.xform = {
+		.aead = {
+			.next = NULL,
+			.type = RTE_CRYPTO_SYM_XFORM_AEAD,
+			.aead = {
+				.op = RTE_CRYPTO_AEAD_OP_ENCRYPT,
+				.algo = RTE_CRYPTO_AEAD_AES_GCM,
+				.key.length = 16,
+				.iv.length = 12,
+				.iv.offset = IV_OFFSET,
+				.digest_length = 16,
+				.aad_length = 12,
+			},
+		},
+	},
+};
+
+struct ipsec_test_data pkt_aes_192_gcm = {
+	.key = {
+		.data = {
+			0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+			0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+			0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c
+		},
+	},
+	.input_text = {
+		.data = {
+			/* IP */
+			0x45, 0x00, 0x00, 0x28, 0xa4, 0xad, 0x40, 0x00,
+			0x40, 0x06, 0x78, 0x80, 0x0a, 0x01, 0x03, 0x8f,
+			0x0a, 0x01, 0x06, 0x12,
+
+			/* TCP */
+			0x80, 0x23, 0x06, 0xb8, 0xcb, 0x71, 0x26, 0x02,
+			0xdd, 0x6b, 0xb0, 0x3e, 0x50, 0x10, 0x16, 0xd0,
+			0x75, 0x67, 0x00, 0x01
+		},
+		.len = 40,
+	},
+	.output_text = {
+		.data = {
+			/* IP - outer header */
+			0x45, 0x00, 0x00, 0x60, 0x69, 0x8f, 0x00, 0x00,
+			0x80, 0x32, 0x4d, 0x89, 0xc0, 0xa8, 0x01, 0x02,
+			0xc0, 0xa8, 0x01, 0x01,
+
+			/* ESP */
+			0x00, 0x00, 0xa5, 0xf8, 0x00, 0x00, 0x00, 0x01,
+
+			/* IV */
+			0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
+
+			/* Data */
+			0xa5, 0xb1, 0xf8, 0x06, 0x60, 0x29, 0xae, 0xa4,
+			0x0e, 0x59, 0x8b, 0x81, 0x22, 0xde, 0x02, 0x42,
+			0x09, 0x38, 0xb3, 0xab, 0x33, 0xf8, 0x28, 0xe6,
+			0x87, 0xb8, 0x85, 0x8b, 0x5b, 0xfb, 0xdb, 0xd0,
+			0x31, 0x5b, 0x27, 0x45, 0x21, 0x4b, 0xcc, 0x77,
+			0x82, 0xac, 0x91, 0x38, 0xf2, 0xbb, 0xbe, 0xe4,
+			0xcf, 0x03, 0x36, 0x89, 0xdd, 0x40, 0xd3, 0x6e,
+			0x54, 0x05, 0x22, 0x22,
+		},
+		.len = 96,
+	},
+	.salt = {
+		.data = {
+			0xca, 0xfe, 0xba, 0xbe
+		},
+		.len = 4,
+	},
+
+	.iv = {
+		.data = {
+			0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88
+		},
+	},
+
+	.ipsec_xform = {
+		.spi = 0xa5f8,
+		.options.esn = 0,
+		.options.udp_encap = 0,
+		.options.copy_dscp = 0,
+		.options.copy_flabel = 0,
+		.options.copy_df = 0,
+		.options.dec_ttl = 0,
+		.options.ecn = 0,
+		.options.stats = 0,
+		.direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
+		.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+		.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+		.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4,
+		.esn_soft_limit = 0,
+		.replay_win_sz = 0,
+	},
+
+	.aead = true,
+
+	.xform = {
+		.aead = {
+			.next = NULL,
+			.type = RTE_CRYPTO_SYM_XFORM_AEAD,
+			.aead = {
+				.op = RTE_CRYPTO_AEAD_OP_ENCRYPT,
+				.algo = RTE_CRYPTO_AEAD_AES_GCM,
+				.key.length = 24,
+				.iv.length = 12,
+				.iv.offset = IV_OFFSET,
+				.digest_length = 16,
+				.aad_length = 12,
+			},
+		},
+	},
+};
+
+struct ipsec_test_data pkt_aes_256_gcm = {
+	.key = {
+		.data = {
+			0xab, 0xbc, 0xcd, 0xde, 0xf0, 0x01, 0x12, 0x23,
+			0x34, 0x45, 0x56, 0x67, 0x78, 0x89, 0x9a, 0xab,
+			0xab, 0xbc, 0xcd, 0xde, 0xf0, 0x01, 0x12, 0x23,
+			0x34, 0x45, 0x56, 0x67, 0x78, 0x89, 0x9a, 0xab,
+		},
+	},
+	.input_text = {
+		.data = {
+			/* IP */
+			0x45, 0x00, 0x00, 0x30, 0x69, 0xa6, 0x40, 0x00,
+			0x80, 0x06, 0x26, 0x90, 0xc0, 0xa8, 0x01, 0x02,
+			0x93, 0x89, 0x15, 0x5e,
+
+			/* TCP */
+			0x0a, 0x9e, 0x00, 0x8b, 0x2d, 0xc5, 0x7e, 0xe0,
+			0x00, 0x00, 0x00, 0x00, 0x70, 0x02, 0x40, 0x00,
+			0x20, 0xbf, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4,
+			0x01, 0x01, 0x04, 0x02,
+		},
+		.len = 48,
+	},
+	.output_text = {
+		.data = {
+			/* IP - outer header */
+			0x45, 0x00, 0x00, 0x68, 0x69, 0x8f, 0x00, 0x00,
+			0x80, 0x32, 0x4d, 0x81, 0xc0, 0xa8, 0x01, 0x02,
+			0xc0, 0xa8, 0x01, 0x01,
+
+			/* ESP */
+			0x4a, 0x2c, 0xbf, 0xe3, 0x00, 0x00, 0x00, 0x01,
+
+			/* IV */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+
+			/* Data */
+			0xff, 0x42, 0x5c, 0x9b, 0x72, 0x45, 0x99, 0xdf,
+			0x7a, 0x3b, 0xcd, 0x51, 0x01, 0x94, 0xe0, 0x0d,
+			0x6a, 0x78, 0x10, 0x7f, 0x1b, 0x0b, 0x1c, 0xbf,
+			0x06, 0xef, 0xae, 0x9d, 0x65, 0xa5, 0xd7, 0x63,
+			0x74, 0x8a, 0x63, 0x79, 0x85, 0x77, 0x1d, 0x34,
+			0x7f, 0x05, 0x45, 0x65, 0x9f, 0x14, 0xe9, 0x9d,
+			0xef, 0x84, 0x2d, 0x8b, 0x00, 0x14, 0x4a, 0x1f,
+			0xec, 0x6a, 0xdf, 0x0c, 0x9a, 0x92, 0x7f, 0xee,
+			0xa6, 0xc5, 0x11, 0x60,
+		},
+		.len = 104,
+	},
+	.salt = {
+		.data = {
+			0x11, 0x22, 0x33, 0x44
+		},
+		.len = 4,
+	},
+
+	.iv = {
+		.data = {
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
+		},
+	},
+
+	.ipsec_xform = {
+		.spi = 0x4a2cbfe3,
+		.options.esn = 0,
+		.options.udp_encap = 0,
+		.options.copy_dscp = 0,
+		.options.copy_flabel = 0,
+		.options.copy_df = 0,
+		.options.dec_ttl = 0,
+		.options.ecn = 0,
+		.options.stats = 0,
+		.direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
+		.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+		.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+		.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4,
+		.esn_soft_limit = 0,
+		.replay_win_sz = 0,
+	},
+
+	.aead = true,
+
+	.xform = {
+		.aead = {
+			.next = NULL,
+			.type = RTE_CRYPTO_SYM_XFORM_AEAD,
+			.aead = {
+				.op = RTE_CRYPTO_AEAD_OP_ENCRYPT,
+				.algo = RTE_CRYPTO_AEAD_AES_GCM,
+				.key.length = 32,
+				.iv.length = 12,
+				.iv.offset = IV_OFFSET,
+				.digest_length = 16,
+				.aad_length = 12,
+			},
+		},
+	},
+};
+
+#endif /* TEST_CRYPTODEV_SECURITY_IPSEC_TEST_VECTORS_H_ */