DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [dpdk-dev 0/2] fips_validation: add SGL and GMAC support
@ 2020-08-18 12:17 Fan Zhang
  2020-08-18 12:17 ` [dpdk-dev] [dpdk-dev 1/2] fips_validation: add SGL support Fan Zhang
                   ` (2 more replies)
  0 siblings, 3 replies; 16+ messages in thread
From: Fan Zhang @ 2020-08-18 12:17 UTC (permalink / raw)
  To: dev; +Cc: akhil.goyal, Fan Zhang

This patchset adds SGL and GMAC support to fips_validation sample
application. The added cmdline option allows user to split the input
data into multiple mbuf segments to test SGL feature of the target
cryptodev PMD; The NIST GCMVS compliant GMAC test method support is also
added in this patchset.

Fan Zhang (2):
  fips_validation: add SGL support
  fips_validation: update GCM test

 doc/guides/rel_notes/release_20_11.rst        |   5 +
 doc/guides/sample_app_ug/fips_validation.rst  |   6 +
 examples/fips_validation/fips_validation.h    |  29 +-
 .../fips_validation/fips_validation_gcm.c     | 118 ++++-
 examples/fips_validation/main.c               | 441 +++++++++++++-----
 5 files changed, 459 insertions(+), 140 deletions(-)

-- 
2.20.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [dpdk-dev] [dpdk-dev 1/2] fips_validation: add SGL support
  2020-08-18 12:17 [dpdk-dev] [dpdk-dev 0/2] fips_validation: add SGL and GMAC support Fan Zhang
@ 2020-08-18 12:17 ` Fan Zhang
  2020-08-18 12:17 ` [dpdk-dev] [dpdk-dev 2/2] fips_validation: update GCM test Fan Zhang
  2020-09-04 16:09 ` [dpdk-dev] [dpdk-dev v2 0/2] fips_validation: add SGL and GMAC support Fan Zhang
  2 siblings, 0 replies; 16+ messages in thread
From: Fan Zhang @ 2020-08-18 12:17 UTC (permalink / raw)
  To: dev; +Cc: akhil.goyal, Fan Zhang

This patch adds SGL support to FIPS sample application.
Originally the application allocates single mbuf of 64KB - 1
bytes data room. With the change the user may reduce the
mbuf dataroom size by using the add cmdline option. If the
input test data is longer than the user provided data room
size the application will automatically build chained mbufs
for the target cryptodev PMD to test.

Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
---
 doc/guides/sample_app_ug/fips_validation.rst |   6 +
 examples/fips_validation/fips_validation.h   |   2 +-
 examples/fips_validation/main.c              | 372 +++++++++++++------
 3 files changed, 265 insertions(+), 115 deletions(-)

diff --git a/doc/guides/sample_app_ug/fips_validation.rst b/doc/guides/sample_app_ug/fips_validation.rst
index 2953fddeb..7bf0eb48a 100644
--- a/doc/guides/sample_app_ug/fips_validation.rst
+++ b/doc/guides/sample_app_ug/fips_validation.rst
@@ -96,6 +96,7 @@ The application requires a number of command line options:
          -- --req-file FILE_PATH/FOLDER_PATH
          --rsp-file FILE_PATH/FOLDER_PATH
          [--cryptodev DEVICE_NAME] [--cryptodev-id ID] [--path-is-folder]
+         --mbuf-dataroom DATAROOM_SIZE
 
 where,
   * req-file: The path of the request file or folder, separated by
@@ -111,6 +112,11 @@ where,
   * path-is-folder: If presented the application expects req-file and rsp-file
     are folder paths.
 
+  * mbuf-dataroom: By default the application creates mbuf pool with maximum
+    possible data room (65535 bytes). If the user wants to test scatter-gather
+    list feature of the PMD he or she may set this value to reduce the dataroom
+    size so that the input data may be splitted into multiple chained mbufs.
+
 
 To run the application in linux environment to test one AES FIPS test data
 file for crypto_aesni_mb PMD, issue the command:
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index 75fa555fa..d48648467 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -12,7 +12,7 @@
 #define MAX_CASE_LINE		15
 #define MAX_LINE_CHAR		204800 /*< max number of characters per line */
 #define MAX_NB_TESTS		10240
-#define MAX_BUF_SIZE		2048
+#define DEF_MBUF_SEG_SIZE	UINT16_MAX
 #define MAX_STRING_SIZE		64
 #define MAX_DIGEST_SIZE		64
 
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index efd32a86a..b2660b0d7 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -17,6 +17,7 @@
 
 #define REQ_FILE_PATH_KEYWORD	"req-file"
 #define RSP_FILE_PATH_KEYWORD	"rsp-file"
+#define MBUF_DATAROOM_KEYWORD	"mbuf-dataroom"
 #define FOLDER_KEYWORD		"path-is-folder"
 #define CRYPTODEV_KEYWORD	"cryptodev"
 #define CRYPTODEV_ID_KEYWORD	"cryptodev-id"
@@ -33,15 +34,19 @@ struct cryptodev_fips_validate_env {
 	const char *req_path;
 	const char *rsp_path;
 	uint32_t is_path_folder;
-	uint32_t dev_id;
+	uint8_t dev_id;
+	uint8_t dev_support_sgl;
+	uint16_t mbuf_data_room;
 	struct rte_mempool *mpool;
 	struct rte_mempool *sess_mpool;
 	struct rte_mempool *sess_priv_mpool;
 	struct rte_mempool *op_pool;
 	struct rte_mbuf *mbuf;
+	uint8_t *digest;
+	uint16_t digest_len;
 	struct rte_crypto_op *op;
 	struct rte_cryptodev_sym_session *sess;
-	uint32_t self_test;
+	uint16_t self_test;
 	struct fips_dev_broken_test_config *broken_test_config;
 } env;
 
@@ -50,8 +55,10 @@ cryptodev_fips_validate_app_int(void)
 {
 	struct rte_cryptodev_config conf = {rte_socket_id(), 1, 0};
 	struct rte_cryptodev_qp_conf qp_conf = {128, NULL, NULL};
+	struct rte_cryptodev_info dev_info;
 	uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(
 			env.dev_id);
+	uint32_t nb_mbufs = UINT16_MAX / env.mbuf_data_room + 1;
 	int ret;
 
 	if (env.self_test) {
@@ -70,8 +77,15 @@ cryptodev_fips_validate_app_int(void)
 	if (ret < 0)
 		return ret;
 
-	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", 128, 0, 0,
-			UINT16_MAX, rte_socket_id());
+	rte_cryptodev_info_get(env.dev_id, &dev_info);
+	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)
+		env.dev_support_sgl = 1;
+	else
+		env.dev_support_sgl = 0;
+
+	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", nb_mbufs,
+			0, 0, sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM +
+			env.mbuf_data_room, rte_socket_id());
 	if (!env.mpool)
 		return ret;
 
@@ -102,10 +116,6 @@ cryptodev_fips_validate_app_int(void)
 	if (!env.op_pool)
 		goto error_exit;
 
-	env.mbuf = rte_pktmbuf_alloc(env.mpool);
-	if (!env.mbuf)
-		goto error_exit;
-
 	env.op = rte_crypto_op_alloc(env.op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
 	if (!env.op)
 		goto error_exit;
@@ -160,7 +170,7 @@ parse_cryptodev_arg(char *arg)
 		return id;
 	}
 
-	env.dev_id = (uint32_t)id;
+	env.dev_id = (uint8_t)id;
 
 	return 0;
 }
@@ -195,15 +205,16 @@ cryptodev_fips_validate_usage(const char *prgname)
 		"  --%s: REQUEST-FILE-PATH\n"
 		"  --%s: RESPONSE-FILE-PATH\n"
 		"  --%s: indicating both paths are folders\n"
+		"  --%s: mbuf dataroom size (default %u bytes)\n"
 		"  --%s: CRYPTODEV-NAME\n"
 		"  --%s: CRYPTODEV-ID-NAME\n"
 		"  --%s: self test indicator\n"
 		"  --%s: self broken test ID\n"
 		"  --%s: self broken test direction\n",
 		prgname, REQ_FILE_PATH_KEYWORD, RSP_FILE_PATH_KEYWORD,
-		FOLDER_KEYWORD, CRYPTODEV_KEYWORD, CRYPTODEV_ID_KEYWORD,
-		CRYPTODEV_ST_KEYWORD, CRYPTODEV_BK_ID_KEYWORD,
-		CRYPTODEV_BK_DIR_KEY);
+		FOLDER_KEYWORD, MBUF_DATAROOM_KEYWORD, DEF_MBUF_SEG_SIZE,
+		CRYPTODEV_KEYWORD, CRYPTODEV_ID_KEYWORD, CRYPTODEV_ST_KEYWORD,
+		CRYPTODEV_BK_ID_KEYWORD, CRYPTODEV_BK_DIR_KEY);
 }
 
 static int
@@ -217,6 +228,7 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 			{REQ_FILE_PATH_KEYWORD, required_argument, 0, 0},
 			{RSP_FILE_PATH_KEYWORD, required_argument, 0, 0},
 			{FOLDER_KEYWORD, no_argument, 0, 0},
+			{MBUF_DATAROOM_KEYWORD, required_argument, 0, 0},
 			{CRYPTODEV_KEYWORD, required_argument, 0, 0},
 			{CRYPTODEV_ID_KEYWORD, required_argument, 0, 0},
 			{CRYPTODEV_ST_KEYWORD, no_argument, 0, 0},
@@ -227,6 +239,14 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 
 	argvopt = argv;
 
+	env.mbuf_data_room = DEF_MBUF_SEG_SIZE;
+	if (rte_cryptodev_count())
+		env.dev_id = 0;
+	else {
+		cryptodev_fips_validate_usage(prgname);
+		return -EINVAL;
+	}
+
 	while ((opt = getopt_long(argc, argvopt, "s:",
 				  lgopts, &option_index)) != EOF) {
 
@@ -305,6 +325,23 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 					cryptodev_fips_validate_usage(prgname);
 					return -EINVAL;
 				}
+			} else if (strcmp(lgopts[option_index].name,
+					MBUF_DATAROOM_KEYWORD) == 0) {
+				uint32_t data_room_size;
+
+				if (parser_read_uint32(&data_room_size,
+						optarg) < 0) {
+					cryptodev_fips_validate_usage(prgname);
+					return -EINVAL;
+				}
+
+				if (data_room_size == 0 ||
+						data_room_size > UINT16_MAX) {
+					cryptodev_fips_validate_usage(prgname);
+					return -EINVAL;
+				}
+
+				env.mbuf_data_room = data_room_size;
 			} else {
 				cryptodev_fips_validate_usage(prgname);
 				return -EINVAL;
@@ -315,8 +352,7 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 		}
 	}
 
-	if (env.req_path == NULL || env.rsp_path == NULL ||
-			env.dev_id == UINT32_MAX) {
+	if (env.req_path == NULL || env.rsp_path == NULL) {
 		cryptodev_fips_validate_usage(prgname);
 		return -EINVAL;
 	}
@@ -451,60 +487,124 @@ struct fips_test_ops {
 } test_ops;
 
 static int
-prepare_cipher_op(void)
+prepare_data_mbufs(struct fips_val *val)
 {
-	struct rte_crypto_sym_op *sym = env.op->sym;
-	uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
+	struct rte_mbuf *m, *head = 0;
+	uint8_t *src = val->val;
+	uint32_t total_len = val->len;
+	uint16_t nb_seg;
+	int ret = 0;
 
-	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
-	rte_pktmbuf_reset(env.mbuf);
-
-	sym->m_src = env.mbuf;
-	sym->cipher.data.offset = 0;
+	if (env.mbuf)
+		rte_pktmbuf_free(env.mbuf);
 
-	memcpy(iv, vec.iv.val, vec.iv.len);
+	if (total_len > RTE_MBUF_MAX_NB_SEGS) {
+		RTE_LOG(ERR, USER1, "Data len %u too big\n", total_len);
+		return -EPERM;
+	}
 
-	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
-		uint8_t *pt;
+	nb_seg = total_len / env.mbuf_data_room;
+	if (total_len % env.mbuf_data_room)
+		nb_seg++;
 
-		if (vec.pt.len > RTE_MBUF_MAX_NB_SEGS) {
-			RTE_LOG(ERR, USER1, "PT len %u\n", vec.pt.len);
-			return -EPERM;
-		}
+	m = rte_pktmbuf_alloc(env.mpool);
+	if (!m) {
+		RTE_LOG(ERR, USER1, "Error %i: Not enough mbuf\n",
+				-ENOMEM);
+		return -ENOMEM;
+	}
+	head = m;
 
-		pt = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.pt.len);
+	while (nb_seg) {
+		uint16_t len = RTE_MIN(total_len, env.mbuf_data_room);
+		uint8_t *dst = (uint8_t *)rte_pktmbuf_append(m, len);
 
-		if (!pt) {
+		if (!dst) {
 			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
 					-ENOMEM);
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto error_exit;
 		}
 
-		memcpy(pt, vec.pt.val, vec.pt.len);
-		sym->cipher.data.length = vec.pt.len;
-
-	} else {
-		uint8_t *ct;
+		memcpy(dst, src, len);
 
-		if (vec.ct.len > RTE_MBUF_MAX_NB_SEGS) {
-			RTE_LOG(ERR, USER1, "CT len %u\n", vec.ct.len);
-			return -EPERM;
+		if (head != m) {
+			ret = rte_pktmbuf_chain(head, m);
+			if (ret) {
+				rte_pktmbuf_free(m);
+				RTE_LOG(ERR, USER1, "Error %i: SGL build\n",
+						ret);
+				goto error_exit;
+			}
 		}
+		total_len -= len;
 
-		ct = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.ct.len);
+		if (total_len) {
+			if (!env.dev_support_sgl) {
+				RTE_LOG(ERR, USER1, "SGL not supported\n");
+				ret = -EPERM;
+				goto error_exit;
+			}
 
-		if (!ct) {
-			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
-					-ENOMEM);
-			return -ENOMEM;
-		}
+			m = rte_pktmbuf_alloc(env.mpool);
+			if (!m) {
+				RTE_LOG(ERR, USER1, "Error %i: No memory\n",
+						-ENOMEM);
+				goto error_exit;
+			}
+		} else
+			break;
+
+		src += len;
+		nb_seg--;
+	}
+
+	if (total_len) {
+		RTE_LOG(ERR, USER1, "Error %i: Failed to store all data\n",
+				-ENOMEM);
+		goto error_exit;
+	}
+
+	env.mbuf = head;
+
+	return 0;
+
+error_exit:
+	if (head)
+		rte_pktmbuf_free(head);
+	return ret;
+}
+
+static int
+prepare_cipher_op(void)
+{
+	struct rte_crypto_sym_op *sym = env.op->sym;
+	uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
+	int ret;
+
+	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+
+	memcpy(iv, vec.iv.val, vec.iv.len);
+
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+		ret = prepare_data_mbufs(&vec.pt);
+		if (ret < 0)
+			return ret;
+
+		sym->cipher.data.length = vec.pt.len;
+	} else {
+		ret = prepare_data_mbufs(&vec.ct);
+		if (ret < 0)
+			return ret;
 
-		memcpy(ct, vec.ct.val, vec.ct.len);
 		sym->cipher.data.length = vec.ct.len;
 	}
 
 	rte_crypto_op_attach_sym_session(env.op, env.sess);
 
+	sym->m_src = env.mbuf;
+	sym->cipher.data.offset = 0;
+
 	return 0;
 }
 
@@ -512,32 +612,33 @@ static int
 prepare_auth_op(void)
 {
 	struct rte_crypto_sym_op *sym = env.op->sym;
-	uint8_t *pt;
+	int ret;
 
 	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
-	rte_pktmbuf_reset(env.mbuf);
 
-	sym->m_src = env.mbuf;
-	sym->auth.data.offset = 0;
+	ret = prepare_data_mbufs(&vec.pt);
+	if (ret < 0)
+		return ret;
 
-	pt = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.pt.len +
-			vec.cipher_auth.digest.len);
+	if (env.digest)
+		rte_free(env.digest);
 
-	if (!pt) {
-		RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
-				-ENOMEM);
+	env.digest = rte_zmalloc(NULL, vec.cipher_auth.digest.len,
+			RTE_CACHE_LINE_SIZE);
+	if (!env.digest) {
+		RTE_LOG(ERR, USER1, "Not enough memory\n");
 		return -ENOMEM;
 	}
+	env.digest_len = vec.cipher_auth.digest.len;
 
+	sym->m_src = env.mbuf;
+	sym->auth.data.offset = 0;
 	sym->auth.data.length = vec.pt.len;
-	sym->auth.digest.data = pt + vec.pt.len;
-	sym->auth.digest.phys_addr = rte_pktmbuf_mtophys_offset(
-			env.mbuf, vec.pt.len);
-
-	memcpy(pt, vec.pt.val, vec.pt.len);
+	sym->auth.digest.data = env.digest;
+	sym->auth.digest.phys_addr = rte_malloc_virt2iova(env.digest);
 
 	if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
-		memcpy(pt + vec.pt.len, vec.cipher_auth.digest.val,
+		memcpy(env.digest, vec.cipher_auth.digest.val,
 				vec.cipher_auth.digest.len);
 
 	rte_crypto_op_attach_sym_session(env.op, env.sess);
@@ -550,65 +651,53 @@ prepare_aead_op(void)
 {
 	struct rte_crypto_sym_op *sym = env.op->sym;
 	uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
+	int ret;
 
 	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
-	rte_pktmbuf_reset(env.mbuf);
 
 	if (info.algo == FIPS_TEST_ALGO_AES_CCM)
-		memcpy(iv + 1, vec.iv.val, vec.iv.len);
-	else
-		memcpy(iv, vec.iv.val, vec.iv.len);
+		iv++;
 
-	sym->m_src = env.mbuf;
-	sym->aead.data.offset = 0;
-	sym->aead.aad.data = vec.aead.aad.val;
-	sym->aead.aad.phys_addr = rte_malloc_virt2iova(sym->aead.aad.data);
+	if (vec.iv.val)
+		memcpy(iv, vec.iv.val, vec.iv.len);
+	else
+		/* if REQ file has iv length but not data, default as all 0 */
+		memset(iv, 0, vec.iv.len);
 
 	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
-		uint8_t *pt;
-
-		if (vec.pt.len > RTE_MBUF_MAX_NB_SEGS) {
-			RTE_LOG(ERR, USER1, "PT len %u\n", vec.pt.len);
-			return -EPERM;
-		}
-
-		pt = (uint8_t *)rte_pktmbuf_append(env.mbuf,
-				vec.pt.len + vec.aead.digest.len);
+		ret = prepare_data_mbufs(&vec.pt);
+		if (ret < 0)
+			return ret;
 
-		if (!pt) {
-			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
-					-ENOMEM);
+		if (env.digest)
+			rte_free(env.digest);
+		env.digest = rte_zmalloc(NULL, vec.aead.digest.len,
+				RTE_CACHE_LINE_SIZE);
+		if (!env.digest) {
+			RTE_LOG(ERR, USER1, "Not enough memory\n");
 			return -ENOMEM;
 		}
+		env.digest_len = vec.cipher_auth.digest.len;
 
-		memcpy(pt, vec.pt.val, vec.pt.len);
 		sym->aead.data.length = vec.pt.len;
-		sym->aead.digest.data = pt + vec.pt.len;
-		sym->aead.digest.phys_addr = rte_pktmbuf_mtophys_offset(
-				env.mbuf, vec.pt.len);
+		sym->aead.digest.data = env.digest;
+		sym->aead.digest.phys_addr = rte_malloc_virt2iova(env.digest);
 	} else {
-		uint8_t *ct;
-
-		if (vec.ct.len > RTE_MBUF_MAX_NB_SEGS) {
-			RTE_LOG(ERR, USER1, "CT len %u\n", vec.ct.len);
-			return -EPERM;
-		}
-
-		ct = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.ct.len);
-
-		if (!ct) {
-			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
-					-ENOMEM);
-			return -ENOMEM;
-		}
+		ret = prepare_data_mbufs(&vec.ct);
+		if (ret < 0)
+			return ret;
 
-		memcpy(ct, vec.ct.val, vec.ct.len);
 		sym->aead.data.length = vec.ct.len;
 		sym->aead.digest.data = vec.aead.digest.val;
 		sym->aead.digest.phys_addr = rte_malloc_virt2iova(
 				sym->aead.digest.data);
 	}
 
+	sym->m_src = env.mbuf;
+	sym->aead.data.offset = 0;
+	sym->aead.aad.data = vec.aead.aad.val;
+	sym->aead.aad.phys_addr = rte_malloc_virt2iova(sym->aead.aad.data);
+
 	rte_crypto_op_attach_sym_session(env.op, env.sess);
 
 	return 0;
@@ -952,11 +1041,44 @@ prepare_xts_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
-static void
+static int
 get_writeback_data(struct fips_val *val)
 {
-	val->val = rte_pktmbuf_mtod(env.mbuf, uint8_t *);
-	val->len = rte_pktmbuf_pkt_len(env.mbuf);
+	struct rte_mbuf *m = env.mbuf;
+	uint16_t total_len = rte_pktmbuf_pkt_len(m) + env.digest_len, tlen;
+	uint8_t *src, *dst, *wb_data;
+
+	/* in case val is reused for MCT test, try to free the buffer first */
+	if (val->val) {
+		free(val->val);
+		val->val = NULL;
+	}
+
+	wb_data = dst = calloc(1, total_len);
+	if (!dst) {
+		RTE_LOG(ERR, USER1, "Not enough memory\n");
+		return -ENOMEM;
+	}
+
+	tlen = total_len;
+
+	while (m && tlen) {
+		uint16_t seg_len = RTE_MIN(rte_pktmbuf_data_len(m), tlen);
+
+		src = rte_pktmbuf_mtod(m, uint8_t *);
+		memcpy(dst, src, seg_len);
+		m = m->next;
+		tlen -= seg_len;
+		dst += seg_len;
+	}
+
+	if (env.digest)
+		memcpy(dst, env.digest, env.digest_len);
+
+	val->val = wb_data;
+	val->len = total_len;
+
+	return 0;
 }
 
 static int
@@ -1015,7 +1137,7 @@ fips_run_test(void)
 static int
 fips_generic_test(void)
 {
-	struct fips_val val;
+	struct fips_val val = {NULL, 0};
 	int ret;
 
 	fips_test_write_one_case();
@@ -1030,7 +1152,9 @@ fips_generic_test(void)
 		return ret;
 	}
 
-	get_writeback_data(&val);
+	ret = get_writeback_data(&val);
+	if (ret < 0)
+		return ret;
 
 	switch (info.file_type) {
 	case FIPS_TYPE_REQ:
@@ -1051,6 +1175,7 @@ fips_generic_test(void)
 	}
 
 	fprintf(info.fp_wr, "\n");
+	free(val.val);
 
 	return 0;
 }
@@ -1061,7 +1186,7 @@ fips_mct_tdes_test(void)
 #define TDES_BLOCK_SIZE		8
 #define TDES_EXTERN_ITER	400
 #define TDES_INTERN_ITER	10000
-	struct fips_val val, val_key;
+	struct fips_val val = {NULL, 0}, val_key;
 	uint8_t prev_out[TDES_BLOCK_SIZE] = {0};
 	uint8_t prev_prev_out[TDES_BLOCK_SIZE] = {0};
 	uint8_t prev_in[TDES_BLOCK_SIZE] = {0};
@@ -1088,7 +1213,9 @@ fips_mct_tdes_test(void)
 				return ret;
 			}
 
-			get_writeback_data(&val);
+			ret = get_writeback_data(&val);
+			if (ret < 0)
+				return ret;
 
 			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
 				memcpy(prev_in, vec.ct.val, TDES_BLOCK_SIZE);
@@ -1215,6 +1342,9 @@ fips_mct_tdes_test(void)
 		}
 	}
 
+	if (val.val)
+		free(val.val);
+
 	return 0;
 }
 
@@ -1224,7 +1354,7 @@ fips_mct_aes_ecb_test(void)
 #define AES_BLOCK_SIZE	16
 #define AES_EXTERN_ITER	100
 #define AES_INTERN_ITER	1000
-	struct fips_val val, val_key;
+	struct fips_val val = {NULL, 0}, val_key;
 	uint8_t prev_out[AES_BLOCK_SIZE] = {0};
 	uint32_t i, j, k;
 	int ret;
@@ -1246,7 +1376,9 @@ fips_mct_aes_ecb_test(void)
 				return ret;
 			}
 
-			get_writeback_data(&val);
+			ret = get_writeback_data(&val);
+			if (ret < 0)
+				return ret;
 
 			if (info.op == FIPS_TEST_ENC_AUTH_GEN)
 				memcpy(vec.pt.val, val.val, AES_BLOCK_SIZE);
@@ -1290,6 +1422,9 @@ fips_mct_aes_ecb_test(void)
 		}
 	}
 
+	if (val.val)
+		free(val.val);
+
 	return 0;
 }
 static int
@@ -1298,7 +1433,7 @@ fips_mct_aes_test(void)
 #define AES_BLOCK_SIZE	16
 #define AES_EXTERN_ITER	100
 #define AES_INTERN_ITER	1000
-	struct fips_val val, val_key;
+	struct fips_val val = {NULL, 0}, val_key;
 	uint8_t prev_out[AES_BLOCK_SIZE] = {0};
 	uint8_t prev_in[AES_BLOCK_SIZE] = {0};
 	uint32_t i, j, k;
@@ -1394,6 +1529,9 @@ fips_mct_aes_test(void)
 			memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
 	}
 
+	if (val.val)
+		free(val.val);
+
 	return 0;
 }
 
@@ -1403,7 +1541,7 @@ fips_mct_sha_test(void)
 #define SHA_EXTERN_ITER	100
 #define SHA_INTERN_ITER	1000
 #define SHA_MD_BLOCK	3
-	struct fips_val val, md[SHA_MD_BLOCK];
+	struct fips_val val = {NULL, 0}, md[SHA_MD_BLOCK];
 	char temp[MAX_DIGEST_SIZE*2];
 	int ret;
 	uint32_t i, j;
@@ -1477,6 +1615,9 @@ fips_mct_sha_test(void)
 
 	rte_free(vec.pt.val);
 
+	if (val.val)
+		free(val.val);
+
 	return 0;
 }
 
@@ -1568,7 +1709,6 @@ fips_test_one_file(void)
 {
 	int fetch_ret = 0, ret;
 
-
 	ret = init_test_ops();
 	if (ret < 0) {
 		RTE_LOG(ERR, USER1, "Error %i: Init test op\n", ret);
@@ -1616,6 +1756,10 @@ fips_test_one_file(void)
 
 	fips_test_clear();
 
-	return ret;
+	if (env.digest)
+		rte_free(env.digest);
+	if (env.mbuf)
+		rte_pktmbuf_free(env.mbuf);
 
+	return ret;
 }
-- 
2.20.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [dpdk-dev] [dpdk-dev 2/2] fips_validation: update GCM test
  2020-08-18 12:17 [dpdk-dev] [dpdk-dev 0/2] fips_validation: add SGL and GMAC support Fan Zhang
  2020-08-18 12:17 ` [dpdk-dev] [dpdk-dev 1/2] fips_validation: add SGL support Fan Zhang
@ 2020-08-18 12:17 ` Fan Zhang
  2020-09-04 16:09 ` [dpdk-dev] [dpdk-dev v2 0/2] fips_validation: add SGL and GMAC support Fan Zhang
  2 siblings, 0 replies; 16+ messages in thread
From: Fan Zhang @ 2020-08-18 12:17 UTC (permalink / raw)
  To: dev; +Cc: akhil.goyal, Fan Zhang, Weqaar Janjua

This patch updates fips validation GCM test capabilities:

- In NIST GCMVS spec GMAC test vectors are the GCM ones with
plaintext length as 0 and uses AAD as input data. Originally
fips_validation tests treats them both as GCM test vectors.
This patch introduce automatic test type recognition between
the two: when plaintext length is 0 the prepare_gmac_xform
and prepare_auth_op functions are called, otherwise
prepare_gcm_xform and prepare_aead_op functions are called.

- NIST GCMVS also specified externally or internally IV
generation. When IV is to be generated by IUT internally IUT
shall store the generated IV in the response file. This patch
also adds the support to that.

Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Signed-off-by: Weqaar Janjua <Weqaar.A.Janjua@intel.com>
---
 doc/guides/rel_notes/release_20_11.rst        |   5 +
 examples/fips_validation/fips_validation.h    |  29 ++++-
 .../fips_validation/fips_validation_gcm.c     | 118 ++++++++++++++++--
 examples/fips_validation/main.c               |  85 ++++++++++---
 4 files changed, 203 insertions(+), 34 deletions(-)

diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
index df227a177..081b5df8d 100644
--- a/doc/guides/rel_notes/release_20_11.rst
+++ b/doc/guides/rel_notes/release_20_11.rst
@@ -55,6 +55,11 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+     ** fips_validation enhancement.**
+
+     fips_vadation sample application is added SGL and NIST GCMVS complaint
+     GMAC test method support.
+
 
 Removed Items
 -------------
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index d48648467..b786e33d9 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -12,7 +12,8 @@
 #define MAX_CASE_LINE		15
 #define MAX_LINE_CHAR		204800 /*< max number of characters per line */
 #define MAX_NB_TESTS		10240
-#define DEF_MBUF_SEG_SIZE	UINT16_MAX
+#define DEF_MBUF_SEG_SIZE	(UINT16_MAX - sizeof(struct rte_mbuf) - \
+				RTE_PKTMBUF_HEADROOM)
 #define MAX_STRING_SIZE		64
 #define MAX_DIGEST_SIZE		64
 
@@ -154,6 +155,11 @@ struct sha_interim_data {
 	enum rte_crypto_auth_algorithm algo;
 };
 
+struct gcm_interim_data {
+	uint8_t is_gmac;
+	uint8_t gen_iv;
+};
+
 struct fips_test_interim_info {
 	FILE *fp_rd;
 	FILE *fp_wr;
@@ -172,6 +178,7 @@ struct fips_test_interim_info {
 		struct tdes_interim_data tdes_data;
 		struct ccm_interim_data ccm_data;
 		struct sha_interim_data sha_data;
+		struct gcm_interim_data gcm_data;
 	} interim_info;
 
 	enum fips_test_op op;
@@ -257,4 +264,24 @@ parse_write_hex_str(struct fips_val *src);
 int
 update_info_vec(uint32_t count);
 
+typedef int (*fips_test_one_case_t)(void);
+typedef int (*fips_prepare_op_t)(void);
+typedef int (*fips_prepare_xform_t)(struct rte_crypto_sym_xform *);
+
+struct fips_test_ops {
+	fips_prepare_xform_t prepare_xform;
+	fips_prepare_op_t prepare_op;
+	fips_test_one_case_t test;
+};
+
+extern struct fips_test_ops test_ops;
+
+int prepare_aead_op(void);
+
+int prepare_auth_op(void);
+
+int prepare_gcm_xform(struct rte_crypto_sym_xform *xform);
+
+int prepare_gmac_xform(struct rte_crypto_sym_xform *xform);
+
 #endif
diff --git a/examples/fips_validation/fips_validation_gcm.c b/examples/fips_validation/fips_validation_gcm.c
index 47576e9a3..df3caa267 100644
--- a/examples/fips_validation/fips_validation_gcm.c
+++ b/examples/fips_validation/fips_validation_gcm.c
@@ -7,6 +7,7 @@
 #include <stdio.h>
 
 #include <rte_cryptodev.h>
+#include <rte_malloc.h>
 
 #include "fips_validation.h"
 
@@ -30,22 +31,93 @@
 
 #define OP_ENC_STR	"Encrypt"
 #define OP_DEC_STR	"Decrypt"
+/* External/Internal IV generation, specified in file name, following NIST
+ * GCMVS Section 6.1
+ */
+#define OP_ENC_EXT_STR	"ExtIV"
+#define OP_ENC_INT_STR	"IntIV"
 
 #define NEG_TEST_STR	"FAIL"
 
+/**
+ * GMAC is essentially zero length plaintext and uses AAD as input data.
+ * NIST does not have GMAC specific test vector but using zero length "PTlen"
+ * and uses AAD as input.
+ **/
+static int
+parser_read_gcm_pt_len(const char *key, char *src,
+		__rte_unused struct fips_val *val)
+{
+	int ret = parser_read_uint32_bit_val(key, src, &vec.pt);
+
+	if (ret < 0)
+		return ret;
+
+	if (vec.pt.len == 0) {
+		info.interim_info.gcm_data.is_gmac = 1;
+		test_ops.prepare_op = prepare_auth_op;
+		test_ops.prepare_xform = prepare_gmac_xform;
+	} else {
+		info.interim_info.gcm_data.is_gmac = 0;
+		test_ops.prepare_op = prepare_aead_op;
+		test_ops.prepare_xform = prepare_gcm_xform;
+	}
+
+	return ret;
+}
+
+static int
+parse_gcm_aad_str(const char *key, char *src,
+		__rte_unused struct fips_val *val)
+{
+	/* For GMAC test vector, AAD is treated as input */
+	if (info.interim_info.gcm_data.is_gmac) {
+		vec.pt.len = vec.aead.aad.len;
+		return parse_uint8_known_len_hex_str(key, src, &vec.pt);
+	} else /* gcm */
+		return parse_uint8_known_len_hex_str(key, src, &vec.aead.aad);
+}
+
+static int
+parse_gcm_pt_ct_str(const char *key, char *src, struct fips_val *val)
+{
+	/* According to NIST GCMVS section 6.1, IUT should generate IV data */
+	if (info.interim_info.gcm_data.gen_iv && vec.iv.len) {
+		uint32_t i;
+
+		if (!vec.iv.val) {
+			vec.iv.val = rte_malloc(0, vec.iv.len, 0);
+			if (!vec.iv.val)
+				return -ENOMEM;
+		}
+
+		for (i = 0; i < vec.iv.len; i++) {
+			int random = rand();
+			vec.iv.val[i] = (uint8_t)random;
+		}
+	}
+
+	/* if PTlen == 0, pt or ct will be handled by AAD later */
+	if (info.interim_info.gcm_data.is_gmac)
+		return 0;
+
+	return parse_uint8_known_len_hex_str(key, src, val);
+}
+
 struct fips_test_callback gcm_dec_vectors[] = {
 		{KEY_STR, parse_uint8_known_len_hex_str, &vec.aead.key},
 		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
-		{CT_STR, parse_uint8_known_len_hex_str, &vec.ct},
-		{AAD_STR, parse_uint8_known_len_hex_str, &vec.aead.aad},
+		{CT_STR, parse_gcm_pt_ct_str, &vec.ct},
+		{AAD_STR, parse_gcm_aad_str, &vec.aead.aad},
 		{TAG_STR, parse_uint8_known_len_hex_str,
 				&vec.aead.digest},
 		{NULL, NULL, NULL} /**< end pointer */
 };
+
 struct fips_test_callback gcm_interim_vectors[] = {
 		{KEYLEN_STR, parser_read_uint32_bit_val, &vec.aead.key},
 		{IVLEN_STR, parser_read_uint32_bit_val, &vec.iv},
-		{PTLEN_STR, parser_read_uint32_bit_val, &vec.pt},
+		{PTLEN_STR, parser_read_gcm_pt_len, &vec.pt},
 		{PTLEN_STR, parser_read_uint32_bit_val, &vec.ct},
 		/**< The NIST test vectors use 'PTlen' to denote input text
 		 *  length in case of decrypt & encrypt operations.
@@ -59,8 +131,8 @@ struct fips_test_callback gcm_interim_vectors[] = {
 struct fips_test_callback gcm_enc_vectors[] = {
 		{KEY_STR, parse_uint8_known_len_hex_str, &vec.aead.key},
 		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
-		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
-		{AAD_STR, parse_uint8_known_len_hex_str, &vec.aead.aad},
+		{PT_STR, parse_gcm_pt_ct_str, &vec.pt},
+		{AAD_STR, parse_gcm_aad_str, &vec.aead.aad},
 		{NULL, NULL, NULL} /**< end pointer */
 };
 
@@ -70,12 +142,28 @@ parse_test_gcm_writeback(struct fips_val *val)
 	struct fips_val tmp_val;
 
 	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+		/* According to NIST GCMVS section 6.1, IUT should provide
+		 * generate IV data
+		 */
+		if (info.interim_info.gcm_data.gen_iv) {
+			fprintf(info.fp_wr, "%s", IV_STR);
+			tmp_val.val = vec.iv.val;
+			tmp_val.len = vec.iv.len;
+
+			parse_write_hex_str(&tmp_val);
+			rte_free(vec.iv.val);
+			vec.iv.val = NULL;
+		}
+
 		fprintf(info.fp_wr, "%s", CT_STR);
 
-		tmp_val.val = val->val;
-		tmp_val.len = vec.pt.len;
+		if (!info.interim_info.gcm_data.is_gmac) {
+			tmp_val.val = val->val;
+			tmp_val.len = vec.pt.len;
 
-		parse_write_hex_str(&tmp_val);
+			parse_write_hex_str(&tmp_val);
+		} else
+			fprintf(info.fp_wr, "\n");
 
 		fprintf(info.fp_wr, "%s", TAG_STR);
 
@@ -86,11 +174,14 @@ parse_test_gcm_writeback(struct fips_val *val)
 	} else {
 		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS) {
 			fprintf(info.fp_wr, "%s", PT_STR);
+			if (!info.interim_info.gcm_data.is_gmac) {
+				fprintf(info.fp_wr, "%s", PT_STR);
+				tmp_val.val = val->val;
+				tmp_val.len = vec.pt.len;
 
-			tmp_val.val = val->val;
-			tmp_val.len = vec.pt.len;
-
-			parse_write_hex_str(&tmp_val);
+				parse_write_hex_str(&tmp_val);
+			} else
+				fprintf(info.fp_wr, "\n");
 		} else
 			fprintf(info.fp_wr, "%s\n", NEG_TEST_STR);
 	}
@@ -108,12 +199,13 @@ parse_test_gcm_init(void)
 	for (i = 0; i < info.nb_vec_lines; i++) {
 		char *line = info.vec[i];
 
-
 		tmp = strstr(line, OP_STR);
 		if (tmp) {
 			if (strstr(line, OP_ENC_STR)) {
 				info.op = FIPS_TEST_ENC_AUTH_GEN;
 				info.callbacks = gcm_enc_vectors;
+				if (strstr(info.file_name, OP_ENC_INT_STR))
+					info.interim_info.gcm_data.gen_iv = 1;
 			} else if (strstr(line, OP_DEC_STR)) {
 				info.op = FIPS_TEST_DEC_AUTH_VERIF;
 				info.callbacks = gcm_dec_vectors;
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index b2660b0d7..aa94ced2b 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -205,7 +205,7 @@ cryptodev_fips_validate_usage(const char *prgname)
 		"  --%s: REQUEST-FILE-PATH\n"
 		"  --%s: RESPONSE-FILE-PATH\n"
 		"  --%s: indicating both paths are folders\n"
-		"  --%s: mbuf dataroom size (default %u bytes)\n"
+		"  --%s: mbuf dataroom size (default %lu bytes)\n"
 		"  --%s: CRYPTODEV-NAME\n"
 		"  --%s: CRYPTODEV-ID-NAME\n"
 		"  --%s: self test indicator\n"
@@ -476,15 +476,7 @@ main(int argc, char *argv[])
 #define IV_OFF (sizeof(struct rte_crypto_op) + sizeof(struct rte_crypto_sym_op))
 #define CRYPTODEV_FIPS_MAX_RETRIES	16
 
-typedef int (*fips_test_one_case_t)(void);
-typedef int (*fips_prepare_op_t)(void);
-typedef int (*fips_prepare_xform_t)(struct rte_crypto_sym_xform *);
-
-struct fips_test_ops {
-	fips_prepare_xform_t prepare_xform;
-	fips_prepare_op_t prepare_op;
-	fips_test_one_case_t test;
-} test_ops;
+struct fips_test_ops test_ops;
 
 static int
 prepare_data_mbufs(struct fips_val *val)
@@ -608,7 +600,7 @@ prepare_cipher_op(void)
 	return 0;
 }
 
-static int
+int
 prepare_auth_op(void)
 {
 	struct rte_crypto_sym_op *sym = env.op->sym;
@@ -616,6 +608,14 @@ prepare_auth_op(void)
 
 	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
 
+	if (vec.iv.len) {
+		uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *,
+				IV_OFF);
+		memset(iv, 0, vec.iv.len);
+		if (vec.iv.val)
+			memcpy(iv, vec.iv.val, vec.iv.len);
+	}
+
 	ret = prepare_data_mbufs(&vec.pt);
 	if (ret < 0)
 		return ret;
@@ -646,7 +646,7 @@ prepare_auth_op(void)
 	return 0;
 }
 
-static int
+int
 prepare_aead_op(void)
 {
 	struct rte_crypto_sym_op *sym = env.op->sym;
@@ -836,7 +836,7 @@ prepare_hmac_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
-static int
+int
 prepare_gcm_xform(struct rte_crypto_sym_xform *xform)
 {
 	const struct rte_cryptodev_symmetric_capability *cap;
@@ -882,6 +882,47 @@ prepare_gcm_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+int
+prepare_gmac_xform(struct rte_crypto_sym_xform *xform)
+{
+	const struct rte_cryptodev_symmetric_capability *cap;
+	struct rte_cryptodev_sym_capability_idx cap_idx;
+	struct rte_crypto_auth_xform *auth_xform = &xform->auth;
+
+	xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
+
+	auth_xform->algo = RTE_CRYPTO_AUTH_AES_GMAC;
+	auth_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_AUTH_OP_GENERATE :
+			RTE_CRYPTO_AUTH_OP_VERIFY;
+	auth_xform->iv.offset = IV_OFF;
+	auth_xform->iv.length = vec.iv.len;
+	auth_xform->digest_length = vec.aead.digest.len;
+	auth_xform->key.data = vec.aead.key.val;
+	auth_xform->key.length = vec.aead.key.len;
+
+	cap_idx.algo.auth = auth_xform->algo;
+	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+
+	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
+	if (!cap) {
+		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
+				env.dev_id);
+		return -EINVAL;
+	}
+
+	if (rte_cryptodev_sym_capability_check_auth(cap,
+			auth_xform->key.length,
+			auth_xform->digest_length, 0) != 0) {
+		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
+				info.device_name, auth_xform->key.length,
+				auth_xform->digest_length);
+		return -EPERM;
+	}
+
+	return 0;
+}
+
 static int
 prepare_cmac_xform(struct rte_crypto_sym_xform *xform)
 {
@@ -1045,7 +1086,8 @@ static int
 get_writeback_data(struct fips_val *val)
 {
 	struct rte_mbuf *m = env.mbuf;
-	uint16_t total_len = rte_pktmbuf_pkt_len(m) + env.digest_len, tlen;
+	uint16_t data_len = rte_pktmbuf_pkt_len(m);
+	uint16_t total_len = data_len + env.digest_len;
 	uint8_t *src, *dst, *wb_data;
 
 	/* in case val is reused for MCT test, try to free the buffer first */
@@ -1056,22 +1098,25 @@ get_writeback_data(struct fips_val *val)
 
 	wb_data = dst = calloc(1, total_len);
 	if (!dst) {
-		RTE_LOG(ERR, USER1, "Not enough memory\n");
+		RTE_LOG(ERR, USER1, "Error %i: Not enough memory\n", -ENOMEM);
 		return -ENOMEM;
 	}
 
-	tlen = total_len;
-
-	while (m && tlen) {
-		uint16_t seg_len = RTE_MIN(rte_pktmbuf_data_len(m), tlen);
+	while (m && data_len) {
+		uint16_t seg_len = RTE_MIN(rte_pktmbuf_data_len(m), data_len);
 
 		src = rte_pktmbuf_mtod(m, uint8_t *);
 		memcpy(dst, src, seg_len);
 		m = m->next;
-		tlen -= seg_len;
+		data_len -= seg_len;
 		dst += seg_len;
 	}
 
+	if (data_len) {
+		RTE_LOG(ERR, USER1, "Error -1: write back data\n");
+		return -1;
+	}
+
 	if (env.digest)
 		memcpy(dst, env.digest, env.digest_len);
 
-- 
2.20.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [dpdk-dev] [dpdk-dev v2 0/2] fips_validation: add SGL and GMAC support
  2020-08-18 12:17 [dpdk-dev] [dpdk-dev 0/2] fips_validation: add SGL and GMAC support Fan Zhang
  2020-08-18 12:17 ` [dpdk-dev] [dpdk-dev 1/2] fips_validation: add SGL support Fan Zhang
  2020-08-18 12:17 ` [dpdk-dev] [dpdk-dev 2/2] fips_validation: update GCM test Fan Zhang
@ 2020-09-04 16:09 ` Fan Zhang
  2020-09-04 16:09   ` [dpdk-dev] [dpdk-dev v2 1/2] fips_validation: add SGL support Fan Zhang
                     ` (3 more replies)
  2 siblings, 4 replies; 16+ messages in thread
From: Fan Zhang @ 2020-09-04 16:09 UTC (permalink / raw)
  To: dev
  Cc: akhil.goyal, fiona.trahe, arkadiuszx.kusztal, adamx.dybkowski, Fan Zhang

This patchset adds SGL and GMAC support to fips_validation sample
application. The added cmdline option allows user to split the input
data into multiple mbuf segments to test SGL feature of the target
cryptodev PMD; The NIST GCMVS compliant GMAC test method support is also
added in this patchset.

V2:
- Fixed compile issue.

Fan Zhang (2):
  fips_validation: add SGL support
  fips_validation: update GCM test

 doc/guides/rel_notes/release_20_11.rst        |   5 +
 doc/guides/sample_app_ug/fips_validation.rst  |   6 +
 examples/fips_validation/fips_validation.h    |  29 +-
 .../fips_validation/fips_validation_gcm.c     | 118 ++++-
 examples/fips_validation/main.c               | 442 +++++++++++++-----
 5 files changed, 460 insertions(+), 140 deletions(-)

-- 
2.20.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [dpdk-dev] [dpdk-dev v2 1/2] fips_validation: add SGL support
  2020-09-04 16:09 ` [dpdk-dev] [dpdk-dev v2 0/2] fips_validation: add SGL and GMAC support Fan Zhang
@ 2020-09-04 16:09   ` Fan Zhang
  2020-09-07 13:32     ` Suanming Mou
  2020-09-17  9:20     ` Griffin, John
  2020-09-04 16:09   ` [dpdk-dev] [dpdk-dev v2 2/2] fips_validation: update GCM test Fan Zhang
                     ` (2 subsequent siblings)
  3 siblings, 2 replies; 16+ messages in thread
From: Fan Zhang @ 2020-09-04 16:09 UTC (permalink / raw)
  To: dev
  Cc: akhil.goyal, fiona.trahe, arkadiuszx.kusztal, adamx.dybkowski, Fan Zhang

This patch adds SGL support to FIPS sample application.
Originally the application allocates single mbuf of 64KB - 1
bytes data room. With the change the user may reduce the
mbuf dataroom size by using the add cmdline option. If the
input test data is longer than the user provided data room
size the application will automatically build chained mbufs
for the target cryptodev PMD to test.

Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
---
 doc/guides/sample_app_ug/fips_validation.rst |   6 +
 examples/fips_validation/fips_validation.h   |   3 +-
 examples/fips_validation/main.c              | 377 +++++++++++++------
 3 files changed, 271 insertions(+), 115 deletions(-)

diff --git a/doc/guides/sample_app_ug/fips_validation.rst b/doc/guides/sample_app_ug/fips_validation.rst
index 2953fddeb..8d3db2214 100644
--- a/doc/guides/sample_app_ug/fips_validation.rst
+++ b/doc/guides/sample_app_ug/fips_validation.rst
@@ -96,6 +96,7 @@ The application requires a number of command line options:
          -- --req-file FILE_PATH/FOLDER_PATH
          --rsp-file FILE_PATH/FOLDER_PATH
          [--cryptodev DEVICE_NAME] [--cryptodev-id ID] [--path-is-folder]
+         --mbuf-dataroom DATAROOM_SIZE
 
 where,
   * req-file: The path of the request file or folder, separated by
@@ -111,6 +112,11 @@ where,
   * path-is-folder: If presented the application expects req-file and rsp-file
     are folder paths.
 
+  * mbuf-dataroom: By default the application creates mbuf pool with maximum
+    possible data room (65535 bytes). If the user wants to test scatter-gather
+    list feature of the PMD he or she may set this value to reduce the dataroom
+    size so that the input data may be dividied into multiple chained mbufs.
+
 
 To run the application in linux environment to test one AES FIPS test data
 file for crypto_aesni_mb PMD, issue the command:
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index 75fa555fa..ecf3d54dd 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -12,7 +12,8 @@
 #define MAX_CASE_LINE		15
 #define MAX_LINE_CHAR		204800 /*< max number of characters per line */
 #define MAX_NB_TESTS		10240
-#define MAX_BUF_SIZE		2048
+#define DEF_MBUF_SEG_SIZE	(UINT16_MAX - sizeof(struct rte_mbuf) - \
+				RTE_PKTMBUF_HEADROOM)
 #define MAX_STRING_SIZE		64
 #define MAX_DIGEST_SIZE		64
 
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index efd32a86a..fadca6e0c 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -17,6 +17,7 @@
 
 #define REQ_FILE_PATH_KEYWORD	"req-file"
 #define RSP_FILE_PATH_KEYWORD	"rsp-file"
+#define MBUF_DATAROOM_KEYWORD	"mbuf-dataroom"
 #define FOLDER_KEYWORD		"path-is-folder"
 #define CRYPTODEV_KEYWORD	"cryptodev"
 #define CRYPTODEV_ID_KEYWORD	"cryptodev-id"
@@ -33,15 +34,19 @@ struct cryptodev_fips_validate_env {
 	const char *req_path;
 	const char *rsp_path;
 	uint32_t is_path_folder;
-	uint32_t dev_id;
+	uint8_t dev_id;
+	uint8_t dev_support_sgl;
+	uint16_t mbuf_data_room;
 	struct rte_mempool *mpool;
 	struct rte_mempool *sess_mpool;
 	struct rte_mempool *sess_priv_mpool;
 	struct rte_mempool *op_pool;
 	struct rte_mbuf *mbuf;
+	uint8_t *digest;
+	uint16_t digest_len;
 	struct rte_crypto_op *op;
 	struct rte_cryptodev_sym_session *sess;
-	uint32_t self_test;
+	uint16_t self_test;
 	struct fips_dev_broken_test_config *broken_test_config;
 } env;
 
@@ -50,8 +55,10 @@ cryptodev_fips_validate_app_int(void)
 {
 	struct rte_cryptodev_config conf = {rte_socket_id(), 1, 0};
 	struct rte_cryptodev_qp_conf qp_conf = {128, NULL, NULL};
+	struct rte_cryptodev_info dev_info;
 	uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(
 			env.dev_id);
+	uint32_t nb_mbufs = UINT16_MAX / env.mbuf_data_room + 1;
 	int ret;
 
 	if (env.self_test) {
@@ -70,8 +77,15 @@ cryptodev_fips_validate_app_int(void)
 	if (ret < 0)
 		return ret;
 
-	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", 128, 0, 0,
-			UINT16_MAX, rte_socket_id());
+	rte_cryptodev_info_get(env.dev_id, &dev_info);
+	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)
+		env.dev_support_sgl = 1;
+	else
+		env.dev_support_sgl = 0;
+
+	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", nb_mbufs,
+			0, 0, sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM +
+			env.mbuf_data_room, rte_socket_id());
 	if (!env.mpool)
 		return ret;
 
@@ -102,10 +116,6 @@ cryptodev_fips_validate_app_int(void)
 	if (!env.op_pool)
 		goto error_exit;
 
-	env.mbuf = rte_pktmbuf_alloc(env.mpool);
-	if (!env.mbuf)
-		goto error_exit;
-
 	env.op = rte_crypto_op_alloc(env.op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
 	if (!env.op)
 		goto error_exit;
@@ -160,7 +170,7 @@ parse_cryptodev_arg(char *arg)
 		return id;
 	}
 
-	env.dev_id = (uint32_t)id;
+	env.dev_id = (uint8_t)id;
 
 	return 0;
 }
@@ -191,19 +201,21 @@ parse_cryptodev_id_arg(char *arg)
 static void
 cryptodev_fips_validate_usage(const char *prgname)
 {
+	uint32_t def_mbuf_seg_size = DEF_MBUF_SEG_SIZE;
 	printf("%s [EAL options] --\n"
 		"  --%s: REQUEST-FILE-PATH\n"
 		"  --%s: RESPONSE-FILE-PATH\n"
 		"  --%s: indicating both paths are folders\n"
+		"  --%s: mbuf dataroom size (default %u bytes)\n"
 		"  --%s: CRYPTODEV-NAME\n"
 		"  --%s: CRYPTODEV-ID-NAME\n"
 		"  --%s: self test indicator\n"
 		"  --%s: self broken test ID\n"
 		"  --%s: self broken test direction\n",
 		prgname, REQ_FILE_PATH_KEYWORD, RSP_FILE_PATH_KEYWORD,
-		FOLDER_KEYWORD, CRYPTODEV_KEYWORD, CRYPTODEV_ID_KEYWORD,
-		CRYPTODEV_ST_KEYWORD, CRYPTODEV_BK_ID_KEYWORD,
-		CRYPTODEV_BK_DIR_KEY);
+		FOLDER_KEYWORD, MBUF_DATAROOM_KEYWORD, def_mbuf_seg_size,
+		CRYPTODEV_KEYWORD, CRYPTODEV_ID_KEYWORD, CRYPTODEV_ST_KEYWORD,
+		CRYPTODEV_BK_ID_KEYWORD, CRYPTODEV_BK_DIR_KEY);
 }
 
 static int
@@ -217,6 +229,7 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 			{REQ_FILE_PATH_KEYWORD, required_argument, 0, 0},
 			{RSP_FILE_PATH_KEYWORD, required_argument, 0, 0},
 			{FOLDER_KEYWORD, no_argument, 0, 0},
+			{MBUF_DATAROOM_KEYWORD, required_argument, 0, 0},
 			{CRYPTODEV_KEYWORD, required_argument, 0, 0},
 			{CRYPTODEV_ID_KEYWORD, required_argument, 0, 0},
 			{CRYPTODEV_ST_KEYWORD, no_argument, 0, 0},
@@ -227,6 +240,14 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 
 	argvopt = argv;
 
+	env.mbuf_data_room = DEF_MBUF_SEG_SIZE;
+	if (rte_cryptodev_count())
+		env.dev_id = 0;
+	else {
+		cryptodev_fips_validate_usage(prgname);
+		return -EINVAL;
+	}
+
 	while ((opt = getopt_long(argc, argvopt, "s:",
 				  lgopts, &option_index)) != EOF) {
 
@@ -305,6 +326,23 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 					cryptodev_fips_validate_usage(prgname);
 					return -EINVAL;
 				}
+			} else if (strcmp(lgopts[option_index].name,
+					MBUF_DATAROOM_KEYWORD) == 0) {
+				uint32_t data_room_size;
+
+				if (parser_read_uint32(&data_room_size,
+						optarg) < 0) {
+					cryptodev_fips_validate_usage(prgname);
+					return -EINVAL;
+				}
+
+				if (data_room_size == 0 ||
+						data_room_size > UINT16_MAX) {
+					cryptodev_fips_validate_usage(prgname);
+					return -EINVAL;
+				}
+
+				env.mbuf_data_room = data_room_size;
 			} else {
 				cryptodev_fips_validate_usage(prgname);
 				return -EINVAL;
@@ -315,8 +353,7 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 		}
 	}
 
-	if (env.req_path == NULL || env.rsp_path == NULL ||
-			env.dev_id == UINT32_MAX) {
+	if (env.req_path == NULL || env.rsp_path == NULL) {
 		cryptodev_fips_validate_usage(prgname);
 		return -EINVAL;
 	}
@@ -451,60 +488,124 @@ struct fips_test_ops {
 } test_ops;
 
 static int
-prepare_cipher_op(void)
+prepare_data_mbufs(struct fips_val *val)
 {
-	struct rte_crypto_sym_op *sym = env.op->sym;
-	uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
+	struct rte_mbuf *m, *head = 0;
+	uint8_t *src = val->val;
+	uint32_t total_len = val->len;
+	uint16_t nb_seg;
+	int ret = 0;
 
-	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
-	rte_pktmbuf_reset(env.mbuf);
-
-	sym->m_src = env.mbuf;
-	sym->cipher.data.offset = 0;
+	if (env.mbuf)
+		rte_pktmbuf_free(env.mbuf);
 
-	memcpy(iv, vec.iv.val, vec.iv.len);
+	if (total_len > RTE_MBUF_MAX_NB_SEGS) {
+		RTE_LOG(ERR, USER1, "Data len %u too big\n", total_len);
+		return -EPERM;
+	}
 
-	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
-		uint8_t *pt;
+	nb_seg = total_len / env.mbuf_data_room;
+	if (total_len % env.mbuf_data_room)
+		nb_seg++;
 
-		if (vec.pt.len > RTE_MBUF_MAX_NB_SEGS) {
-			RTE_LOG(ERR, USER1, "PT len %u\n", vec.pt.len);
-			return -EPERM;
-		}
+	m = rte_pktmbuf_alloc(env.mpool);
+	if (!m) {
+		RTE_LOG(ERR, USER1, "Error %i: Not enough mbuf\n",
+				-ENOMEM);
+		return -ENOMEM;
+	}
+	head = m;
 
-		pt = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.pt.len);
+	while (nb_seg) {
+		uint16_t len = RTE_MIN(total_len, env.mbuf_data_room);
+		uint8_t *dst = (uint8_t *)rte_pktmbuf_append(m, len);
 
-		if (!pt) {
+		if (!dst) {
 			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
 					-ENOMEM);
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto error_exit;
 		}
 
-		memcpy(pt, vec.pt.val, vec.pt.len);
-		sym->cipher.data.length = vec.pt.len;
+		memcpy(dst, src, len);
 
-	} else {
-		uint8_t *ct;
-
-		if (vec.ct.len > RTE_MBUF_MAX_NB_SEGS) {
-			RTE_LOG(ERR, USER1, "CT len %u\n", vec.ct.len);
-			return -EPERM;
+		if (head != m) {
+			ret = rte_pktmbuf_chain(head, m);
+			if (ret) {
+				rte_pktmbuf_free(m);
+				RTE_LOG(ERR, USER1, "Error %i: SGL build\n",
+						ret);
+				goto error_exit;
+			}
 		}
+		total_len -= len;
 
-		ct = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.ct.len);
+		if (total_len) {
+			if (!env.dev_support_sgl) {
+				RTE_LOG(ERR, USER1, "SGL not supported\n");
+				ret = -EPERM;
+				goto error_exit;
+			}
 
-		if (!ct) {
-			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
-					-ENOMEM);
-			return -ENOMEM;
-		}
+			m = rte_pktmbuf_alloc(env.mpool);
+			if (!m) {
+				RTE_LOG(ERR, USER1, "Error %i: No memory\n",
+						-ENOMEM);
+				goto error_exit;
+			}
+		} else
+			break;
+
+		src += len;
+		nb_seg--;
+	}
+
+	if (total_len) {
+		RTE_LOG(ERR, USER1, "Error %i: Failed to store all data\n",
+				-ENOMEM);
+		goto error_exit;
+	}
+
+	env.mbuf = head;
+
+	return 0;
+
+error_exit:
+	if (head)
+		rte_pktmbuf_free(head);
+	return ret;
+}
+
+static int
+prepare_cipher_op(void)
+{
+	struct rte_crypto_sym_op *sym = env.op->sym;
+	uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
+	int ret;
+
+	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+
+	memcpy(iv, vec.iv.val, vec.iv.len);
+
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+		ret = prepare_data_mbufs(&vec.pt);
+		if (ret < 0)
+			return ret;
+
+		sym->cipher.data.length = vec.pt.len;
+	} else {
+		ret = prepare_data_mbufs(&vec.ct);
+		if (ret < 0)
+			return ret;
 
-		memcpy(ct, vec.ct.val, vec.ct.len);
 		sym->cipher.data.length = vec.ct.len;
 	}
 
 	rte_crypto_op_attach_sym_session(env.op, env.sess);
 
+	sym->m_src = env.mbuf;
+	sym->cipher.data.offset = 0;
+
 	return 0;
 }
 
@@ -512,32 +613,33 @@ static int
 prepare_auth_op(void)
 {
 	struct rte_crypto_sym_op *sym = env.op->sym;
-	uint8_t *pt;
+	int ret;
 
 	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
-	rte_pktmbuf_reset(env.mbuf);
 
-	sym->m_src = env.mbuf;
-	sym->auth.data.offset = 0;
+	ret = prepare_data_mbufs(&vec.pt);
+	if (ret < 0)
+		return ret;
 
-	pt = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.pt.len +
-			vec.cipher_auth.digest.len);
+	if (env.digest)
+		rte_free(env.digest);
 
-	if (!pt) {
-		RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
-				-ENOMEM);
+	env.digest = rte_zmalloc(NULL, vec.cipher_auth.digest.len,
+			RTE_CACHE_LINE_SIZE);
+	if (!env.digest) {
+		RTE_LOG(ERR, USER1, "Not enough memory\n");
 		return -ENOMEM;
 	}
+	env.digest_len = vec.cipher_auth.digest.len;
 
+	sym->m_src = env.mbuf;
+	sym->auth.data.offset = 0;
 	sym->auth.data.length = vec.pt.len;
-	sym->auth.digest.data = pt + vec.pt.len;
-	sym->auth.digest.phys_addr = rte_pktmbuf_mtophys_offset(
-			env.mbuf, vec.pt.len);
-
-	memcpy(pt, vec.pt.val, vec.pt.len);
+	sym->auth.digest.data = env.digest;
+	sym->auth.digest.phys_addr = rte_malloc_virt2iova(env.digest);
 
 	if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
-		memcpy(pt + vec.pt.len, vec.cipher_auth.digest.val,
+		memcpy(env.digest, vec.cipher_auth.digest.val,
 				vec.cipher_auth.digest.len);
 
 	rte_crypto_op_attach_sym_session(env.op, env.sess);
@@ -550,65 +652,53 @@ prepare_aead_op(void)
 {
 	struct rte_crypto_sym_op *sym = env.op->sym;
 	uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
+	int ret;
 
 	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
-	rte_pktmbuf_reset(env.mbuf);
 
 	if (info.algo == FIPS_TEST_ALGO_AES_CCM)
-		memcpy(iv + 1, vec.iv.val, vec.iv.len);
-	else
-		memcpy(iv, vec.iv.val, vec.iv.len);
+		iv++;
 
-	sym->m_src = env.mbuf;
-	sym->aead.data.offset = 0;
-	sym->aead.aad.data = vec.aead.aad.val;
-	sym->aead.aad.phys_addr = rte_malloc_virt2iova(sym->aead.aad.data);
+	if (vec.iv.val)
+		memcpy(iv, vec.iv.val, vec.iv.len);
+	else
+		/* if REQ file has iv length but not data, default as all 0 */
+		memset(iv, 0, vec.iv.len);
 
 	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
-		uint8_t *pt;
-
-		if (vec.pt.len > RTE_MBUF_MAX_NB_SEGS) {
-			RTE_LOG(ERR, USER1, "PT len %u\n", vec.pt.len);
-			return -EPERM;
-		}
-
-		pt = (uint8_t *)rte_pktmbuf_append(env.mbuf,
-				vec.pt.len + vec.aead.digest.len);
+		ret = prepare_data_mbufs(&vec.pt);
+		if (ret < 0)
+			return ret;
 
-		if (!pt) {
-			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
-					-ENOMEM);
+		if (env.digest)
+			rte_free(env.digest);
+		env.digest = rte_zmalloc(NULL, vec.aead.digest.len,
+				RTE_CACHE_LINE_SIZE);
+		if (!env.digest) {
+			RTE_LOG(ERR, USER1, "Not enough memory\n");
 			return -ENOMEM;
 		}
+		env.digest_len = vec.cipher_auth.digest.len;
 
-		memcpy(pt, vec.pt.val, vec.pt.len);
 		sym->aead.data.length = vec.pt.len;
-		sym->aead.digest.data = pt + vec.pt.len;
-		sym->aead.digest.phys_addr = rte_pktmbuf_mtophys_offset(
-				env.mbuf, vec.pt.len);
+		sym->aead.digest.data = env.digest;
+		sym->aead.digest.phys_addr = rte_malloc_virt2iova(env.digest);
 	} else {
-		uint8_t *ct;
-
-		if (vec.ct.len > RTE_MBUF_MAX_NB_SEGS) {
-			RTE_LOG(ERR, USER1, "CT len %u\n", vec.ct.len);
-			return -EPERM;
-		}
-
-		ct = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.ct.len);
-
-		if (!ct) {
-			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
-					-ENOMEM);
-			return -ENOMEM;
-		}
+		ret = prepare_data_mbufs(&vec.ct);
+		if (ret < 0)
+			return ret;
 
-		memcpy(ct, vec.ct.val, vec.ct.len);
 		sym->aead.data.length = vec.ct.len;
 		sym->aead.digest.data = vec.aead.digest.val;
 		sym->aead.digest.phys_addr = rte_malloc_virt2iova(
 				sym->aead.digest.data);
 	}
 
+	sym->m_src = env.mbuf;
+	sym->aead.data.offset = 0;
+	sym->aead.aad.data = vec.aead.aad.val;
+	sym->aead.aad.phys_addr = rte_malloc_virt2iova(sym->aead.aad.data);
+
 	rte_crypto_op_attach_sym_session(env.op, env.sess);
 
 	return 0;
@@ -952,11 +1042,48 @@ prepare_xts_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
-static void
+static int
 get_writeback_data(struct fips_val *val)
 {
-	val->val = rte_pktmbuf_mtod(env.mbuf, uint8_t *);
-	val->len = rte_pktmbuf_pkt_len(env.mbuf);
+	struct rte_mbuf *m = env.mbuf;
+	uint16_t data_len = rte_pktmbuf_pkt_len(m);
+	uint16_t total_len = data_len + env.digest_len;
+	uint8_t *src, *dst, *wb_data;
+
+	/* in case val is reused for MCT test, try to free the buffer first */
+	if (val->val) {
+		free(val->val);
+		val->val = NULL;
+	}
+
+	wb_data = dst = calloc(1, total_len);
+	if (!dst) {
+		RTE_LOG(ERR, USER1, "Error %i: Not enough memory\n", -ENOMEM);
+		return -ENOMEM;
+	}
+
+	while (m && data_len) {
+		uint16_t seg_len = RTE_MIN(rte_pktmbuf_data_len(m), data_len);
+
+		src = rte_pktmbuf_mtod(m, uint8_t *);
+		memcpy(dst, src, seg_len);
+		m = m->next;
+		data_len -= seg_len;
+		dst += seg_len;
+	}
+
+	if (data_len) {
+		RTE_LOG(ERR, USER1, "Error -1: write back data\n");
+		return -1;
+	}
+
+	if (env.digest)
+		memcpy(dst, env.digest, env.digest_len);
+
+	val->val = wb_data;
+	val->len = total_len;
+
+	return 0;
 }
 
 static int
@@ -1015,7 +1142,7 @@ fips_run_test(void)
 static int
 fips_generic_test(void)
 {
-	struct fips_val val;
+	struct fips_val val = {NULL, 0};
 	int ret;
 
 	fips_test_write_one_case();
@@ -1030,7 +1157,9 @@ fips_generic_test(void)
 		return ret;
 	}
 
-	get_writeback_data(&val);
+	ret = get_writeback_data(&val);
+	if (ret < 0)
+		return ret;
 
 	switch (info.file_type) {
 	case FIPS_TYPE_REQ:
@@ -1051,6 +1180,7 @@ fips_generic_test(void)
 	}
 
 	fprintf(info.fp_wr, "\n");
+	free(val.val);
 
 	return 0;
 }
@@ -1061,7 +1191,7 @@ fips_mct_tdes_test(void)
 #define TDES_BLOCK_SIZE		8
 #define TDES_EXTERN_ITER	400
 #define TDES_INTERN_ITER	10000
-	struct fips_val val, val_key;
+	struct fips_val val = {NULL, 0}, val_key;
 	uint8_t prev_out[TDES_BLOCK_SIZE] = {0};
 	uint8_t prev_prev_out[TDES_BLOCK_SIZE] = {0};
 	uint8_t prev_in[TDES_BLOCK_SIZE] = {0};
@@ -1088,7 +1218,9 @@ fips_mct_tdes_test(void)
 				return ret;
 			}
 
-			get_writeback_data(&val);
+			ret = get_writeback_data(&val);
+			if (ret < 0)
+				return ret;
 
 			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
 				memcpy(prev_in, vec.ct.val, TDES_BLOCK_SIZE);
@@ -1215,6 +1347,9 @@ fips_mct_tdes_test(void)
 		}
 	}
 
+	if (val.val)
+		free(val.val);
+
 	return 0;
 }
 
@@ -1224,7 +1359,7 @@ fips_mct_aes_ecb_test(void)
 #define AES_BLOCK_SIZE	16
 #define AES_EXTERN_ITER	100
 #define AES_INTERN_ITER	1000
-	struct fips_val val, val_key;
+	struct fips_val val = {NULL, 0}, val_key;
 	uint8_t prev_out[AES_BLOCK_SIZE] = {0};
 	uint32_t i, j, k;
 	int ret;
@@ -1246,7 +1381,9 @@ fips_mct_aes_ecb_test(void)
 				return ret;
 			}
 
-			get_writeback_data(&val);
+			ret = get_writeback_data(&val);
+			if (ret < 0)
+				return ret;
 
 			if (info.op == FIPS_TEST_ENC_AUTH_GEN)
 				memcpy(vec.pt.val, val.val, AES_BLOCK_SIZE);
@@ -1290,6 +1427,9 @@ fips_mct_aes_ecb_test(void)
 		}
 	}
 
+	if (val.val)
+		free(val.val);
+
 	return 0;
 }
 static int
@@ -1298,7 +1438,7 @@ fips_mct_aes_test(void)
 #define AES_BLOCK_SIZE	16
 #define AES_EXTERN_ITER	100
 #define AES_INTERN_ITER	1000
-	struct fips_val val, val_key;
+	struct fips_val val = {NULL, 0}, val_key;
 	uint8_t prev_out[AES_BLOCK_SIZE] = {0};
 	uint8_t prev_in[AES_BLOCK_SIZE] = {0};
 	uint32_t i, j, k;
@@ -1394,6 +1534,9 @@ fips_mct_aes_test(void)
 			memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
 	}
 
+	if (val.val)
+		free(val.val);
+
 	return 0;
 }
 
@@ -1403,7 +1546,7 @@ fips_mct_sha_test(void)
 #define SHA_EXTERN_ITER	100
 #define SHA_INTERN_ITER	1000
 #define SHA_MD_BLOCK	3
-	struct fips_val val, md[SHA_MD_BLOCK];
+	struct fips_val val = {NULL, 0}, md[SHA_MD_BLOCK];
 	char temp[MAX_DIGEST_SIZE*2];
 	int ret;
 	uint32_t i, j;
@@ -1477,6 +1620,9 @@ fips_mct_sha_test(void)
 
 	rte_free(vec.pt.val);
 
+	if (val.val)
+		free(val.val);
+
 	return 0;
 }
 
@@ -1568,7 +1714,6 @@ fips_test_one_file(void)
 {
 	int fetch_ret = 0, ret;
 
-
 	ret = init_test_ops();
 	if (ret < 0) {
 		RTE_LOG(ERR, USER1, "Error %i: Init test op\n", ret);
@@ -1616,6 +1761,10 @@ fips_test_one_file(void)
 
 	fips_test_clear();
 
-	return ret;
+	if (env.digest)
+		rte_free(env.digest);
+	if (env.mbuf)
+		rte_pktmbuf_free(env.mbuf);
 
+	return ret;
 }
-- 
2.20.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [dpdk-dev] [dpdk-dev v2 2/2] fips_validation: update GCM test
  2020-09-04 16:09 ` [dpdk-dev] [dpdk-dev v2 0/2] fips_validation: add SGL and GMAC support Fan Zhang
  2020-09-04 16:09   ` [dpdk-dev] [dpdk-dev v2 1/2] fips_validation: add SGL support Fan Zhang
@ 2020-09-04 16:09   ` Fan Zhang
  2020-09-17  9:20     ` Griffin, John
  2020-10-09 18:23   ` [dpdk-dev] [dpdk-dev v2 0/2] fips_validation: add SGL and GMAC support Akhil Goyal
  2020-10-09 20:08   ` [dpdk-dev] [dpdk-dev v3 " Fan Zhang
  3 siblings, 1 reply; 16+ messages in thread
From: Fan Zhang @ 2020-09-04 16:09 UTC (permalink / raw)
  To: dev
  Cc: akhil.goyal, fiona.trahe, arkadiuszx.kusztal, adamx.dybkowski,
	Fan Zhang, Weqaar Janjua

This patch updates fips validation GCM test capabilities:

- In NIST GCMVS spec GMAC test vectors are the GCM ones with
plaintext length as 0 and uses AAD as input data. Originally
fips_validation tests treats them both as GCM test vectors.
This patch introduce automatic test type recognition between
the two: when plaintext length is 0 the prepare_gmac_xform
and prepare_auth_op functions are called, otherwise
prepare_gcm_xform and prepare_aead_op functions are called.

- NIST GCMVS also specified externally or internally IV
generation. When IV is to be generated by IUT internally IUT
shall store the generated IV in the response file. This patch
also adds the support to that.

Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Signed-off-by: Weqaar Janjua <Weqaar.A.Janjua@intel.com>
---
 doc/guides/rel_notes/release_20_11.rst        |   5 +
 examples/fips_validation/fips_validation.h    |  26 ++++
 .../fips_validation/fips_validation_gcm.c     | 118 ++++++++++++++++--
 examples/fips_validation/main.c               |  65 ++++++++--
 4 files changed, 189 insertions(+), 25 deletions(-)

diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
index df227a177..081b5df8d 100644
--- a/doc/guides/rel_notes/release_20_11.rst
+++ b/doc/guides/rel_notes/release_20_11.rst
@@ -55,6 +55,11 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+     ** fips_validation enhancement.**
+
+     fips_vadation sample application is added SGL and NIST GCMVS complaint
+     GMAC test method support.
+
 
 Removed Items
 -------------
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index ecf3d54dd..b786e33d9 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -155,6 +155,11 @@ struct sha_interim_data {
 	enum rte_crypto_auth_algorithm algo;
 };
 
+struct gcm_interim_data {
+	uint8_t is_gmac;
+	uint8_t gen_iv;
+};
+
 struct fips_test_interim_info {
 	FILE *fp_rd;
 	FILE *fp_wr;
@@ -173,6 +178,7 @@ struct fips_test_interim_info {
 		struct tdes_interim_data tdes_data;
 		struct ccm_interim_data ccm_data;
 		struct sha_interim_data sha_data;
+		struct gcm_interim_data gcm_data;
 	} interim_info;
 
 	enum fips_test_op op;
@@ -258,4 +264,24 @@ parse_write_hex_str(struct fips_val *src);
 int
 update_info_vec(uint32_t count);
 
+typedef int (*fips_test_one_case_t)(void);
+typedef int (*fips_prepare_op_t)(void);
+typedef int (*fips_prepare_xform_t)(struct rte_crypto_sym_xform *);
+
+struct fips_test_ops {
+	fips_prepare_xform_t prepare_xform;
+	fips_prepare_op_t prepare_op;
+	fips_test_one_case_t test;
+};
+
+extern struct fips_test_ops test_ops;
+
+int prepare_aead_op(void);
+
+int prepare_auth_op(void);
+
+int prepare_gcm_xform(struct rte_crypto_sym_xform *xform);
+
+int prepare_gmac_xform(struct rte_crypto_sym_xform *xform);
+
 #endif
diff --git a/examples/fips_validation/fips_validation_gcm.c b/examples/fips_validation/fips_validation_gcm.c
index 47576e9a3..df3caa267 100644
--- a/examples/fips_validation/fips_validation_gcm.c
+++ b/examples/fips_validation/fips_validation_gcm.c
@@ -7,6 +7,7 @@
 #include <stdio.h>
 
 #include <rte_cryptodev.h>
+#include <rte_malloc.h>
 
 #include "fips_validation.h"
 
@@ -30,22 +31,93 @@
 
 #define OP_ENC_STR	"Encrypt"
 #define OP_DEC_STR	"Decrypt"
+/* External/Internal IV generation, specified in file name, following NIST
+ * GCMVS Section 6.1
+ */
+#define OP_ENC_EXT_STR	"ExtIV"
+#define OP_ENC_INT_STR	"IntIV"
 
 #define NEG_TEST_STR	"FAIL"
 
+/**
+ * GMAC is essentially zero length plaintext and uses AAD as input data.
+ * NIST does not have GMAC specific test vector but using zero length "PTlen"
+ * and uses AAD as input.
+ **/
+static int
+parser_read_gcm_pt_len(const char *key, char *src,
+		__rte_unused struct fips_val *val)
+{
+	int ret = parser_read_uint32_bit_val(key, src, &vec.pt);
+
+	if (ret < 0)
+		return ret;
+
+	if (vec.pt.len == 0) {
+		info.interim_info.gcm_data.is_gmac = 1;
+		test_ops.prepare_op = prepare_auth_op;
+		test_ops.prepare_xform = prepare_gmac_xform;
+	} else {
+		info.interim_info.gcm_data.is_gmac = 0;
+		test_ops.prepare_op = prepare_aead_op;
+		test_ops.prepare_xform = prepare_gcm_xform;
+	}
+
+	return ret;
+}
+
+static int
+parse_gcm_aad_str(const char *key, char *src,
+		__rte_unused struct fips_val *val)
+{
+	/* For GMAC test vector, AAD is treated as input */
+	if (info.interim_info.gcm_data.is_gmac) {
+		vec.pt.len = vec.aead.aad.len;
+		return parse_uint8_known_len_hex_str(key, src, &vec.pt);
+	} else /* gcm */
+		return parse_uint8_known_len_hex_str(key, src, &vec.aead.aad);
+}
+
+static int
+parse_gcm_pt_ct_str(const char *key, char *src, struct fips_val *val)
+{
+	/* According to NIST GCMVS section 6.1, IUT should generate IV data */
+	if (info.interim_info.gcm_data.gen_iv && vec.iv.len) {
+		uint32_t i;
+
+		if (!vec.iv.val) {
+			vec.iv.val = rte_malloc(0, vec.iv.len, 0);
+			if (!vec.iv.val)
+				return -ENOMEM;
+		}
+
+		for (i = 0; i < vec.iv.len; i++) {
+			int random = rand();
+			vec.iv.val[i] = (uint8_t)random;
+		}
+	}
+
+	/* if PTlen == 0, pt or ct will be handled by AAD later */
+	if (info.interim_info.gcm_data.is_gmac)
+		return 0;
+
+	return parse_uint8_known_len_hex_str(key, src, val);
+}
+
 struct fips_test_callback gcm_dec_vectors[] = {
 		{KEY_STR, parse_uint8_known_len_hex_str, &vec.aead.key},
 		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
-		{CT_STR, parse_uint8_known_len_hex_str, &vec.ct},
-		{AAD_STR, parse_uint8_known_len_hex_str, &vec.aead.aad},
+		{CT_STR, parse_gcm_pt_ct_str, &vec.ct},
+		{AAD_STR, parse_gcm_aad_str, &vec.aead.aad},
 		{TAG_STR, parse_uint8_known_len_hex_str,
 				&vec.aead.digest},
 		{NULL, NULL, NULL} /**< end pointer */
 };
+
 struct fips_test_callback gcm_interim_vectors[] = {
 		{KEYLEN_STR, parser_read_uint32_bit_val, &vec.aead.key},
 		{IVLEN_STR, parser_read_uint32_bit_val, &vec.iv},
-		{PTLEN_STR, parser_read_uint32_bit_val, &vec.pt},
+		{PTLEN_STR, parser_read_gcm_pt_len, &vec.pt},
 		{PTLEN_STR, parser_read_uint32_bit_val, &vec.ct},
 		/**< The NIST test vectors use 'PTlen' to denote input text
 		 *  length in case of decrypt & encrypt operations.
@@ -59,8 +131,8 @@ struct fips_test_callback gcm_interim_vectors[] = {
 struct fips_test_callback gcm_enc_vectors[] = {
 		{KEY_STR, parse_uint8_known_len_hex_str, &vec.aead.key},
 		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
-		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
-		{AAD_STR, parse_uint8_known_len_hex_str, &vec.aead.aad},
+		{PT_STR, parse_gcm_pt_ct_str, &vec.pt},
+		{AAD_STR, parse_gcm_aad_str, &vec.aead.aad},
 		{NULL, NULL, NULL} /**< end pointer */
 };
 
@@ -70,12 +142,28 @@ parse_test_gcm_writeback(struct fips_val *val)
 	struct fips_val tmp_val;
 
 	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+		/* According to NIST GCMVS section 6.1, IUT should provide
+		 * generate IV data
+		 */
+		if (info.interim_info.gcm_data.gen_iv) {
+			fprintf(info.fp_wr, "%s", IV_STR);
+			tmp_val.val = vec.iv.val;
+			tmp_val.len = vec.iv.len;
+
+			parse_write_hex_str(&tmp_val);
+			rte_free(vec.iv.val);
+			vec.iv.val = NULL;
+		}
+
 		fprintf(info.fp_wr, "%s", CT_STR);
 
-		tmp_val.val = val->val;
-		tmp_val.len = vec.pt.len;
+		if (!info.interim_info.gcm_data.is_gmac) {
+			tmp_val.val = val->val;
+			tmp_val.len = vec.pt.len;
 
-		parse_write_hex_str(&tmp_val);
+			parse_write_hex_str(&tmp_val);
+		} else
+			fprintf(info.fp_wr, "\n");
 
 		fprintf(info.fp_wr, "%s", TAG_STR);
 
@@ -86,11 +174,14 @@ parse_test_gcm_writeback(struct fips_val *val)
 	} else {
 		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS) {
 			fprintf(info.fp_wr, "%s", PT_STR);
+			if (!info.interim_info.gcm_data.is_gmac) {
+				fprintf(info.fp_wr, "%s", PT_STR);
+				tmp_val.val = val->val;
+				tmp_val.len = vec.pt.len;
 
-			tmp_val.val = val->val;
-			tmp_val.len = vec.pt.len;
-
-			parse_write_hex_str(&tmp_val);
+				parse_write_hex_str(&tmp_val);
+			} else
+				fprintf(info.fp_wr, "\n");
 		} else
 			fprintf(info.fp_wr, "%s\n", NEG_TEST_STR);
 	}
@@ -108,12 +199,13 @@ parse_test_gcm_init(void)
 	for (i = 0; i < info.nb_vec_lines; i++) {
 		char *line = info.vec[i];
 
-
 		tmp = strstr(line, OP_STR);
 		if (tmp) {
 			if (strstr(line, OP_ENC_STR)) {
 				info.op = FIPS_TEST_ENC_AUTH_GEN;
 				info.callbacks = gcm_enc_vectors;
+				if (strstr(info.file_name, OP_ENC_INT_STR))
+					info.interim_info.gcm_data.gen_iv = 1;
 			} else if (strstr(line, OP_DEC_STR)) {
 				info.op = FIPS_TEST_DEC_AUTH_VERIF;
 				info.callbacks = gcm_dec_vectors;
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index fadca6e0c..8c32202dc 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -477,15 +477,7 @@ main(int argc, char *argv[])
 #define IV_OFF (sizeof(struct rte_crypto_op) + sizeof(struct rte_crypto_sym_op))
 #define CRYPTODEV_FIPS_MAX_RETRIES	16
 
-typedef int (*fips_test_one_case_t)(void);
-typedef int (*fips_prepare_op_t)(void);
-typedef int (*fips_prepare_xform_t)(struct rte_crypto_sym_xform *);
-
-struct fips_test_ops {
-	fips_prepare_xform_t prepare_xform;
-	fips_prepare_op_t prepare_op;
-	fips_test_one_case_t test;
-} test_ops;
+struct fips_test_ops test_ops;
 
 static int
 prepare_data_mbufs(struct fips_val *val)
@@ -609,7 +601,7 @@ prepare_cipher_op(void)
 	return 0;
 }
 
-static int
+int
 prepare_auth_op(void)
 {
 	struct rte_crypto_sym_op *sym = env.op->sym;
@@ -617,6 +609,14 @@ prepare_auth_op(void)
 
 	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
 
+	if (vec.iv.len) {
+		uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *,
+				IV_OFF);
+		memset(iv, 0, vec.iv.len);
+		if (vec.iv.val)
+			memcpy(iv, vec.iv.val, vec.iv.len);
+	}
+
 	ret = prepare_data_mbufs(&vec.pt);
 	if (ret < 0)
 		return ret;
@@ -647,7 +647,7 @@ prepare_auth_op(void)
 	return 0;
 }
 
-static int
+int
 prepare_aead_op(void)
 {
 	struct rte_crypto_sym_op *sym = env.op->sym;
@@ -837,7 +837,7 @@ prepare_hmac_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
-static int
+int
 prepare_gcm_xform(struct rte_crypto_sym_xform *xform)
 {
 	const struct rte_cryptodev_symmetric_capability *cap;
@@ -883,6 +883,47 @@ prepare_gcm_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+int
+prepare_gmac_xform(struct rte_crypto_sym_xform *xform)
+{
+	const struct rte_cryptodev_symmetric_capability *cap;
+	struct rte_cryptodev_sym_capability_idx cap_idx;
+	struct rte_crypto_auth_xform *auth_xform = &xform->auth;
+
+	xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
+
+	auth_xform->algo = RTE_CRYPTO_AUTH_AES_GMAC;
+	auth_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_AUTH_OP_GENERATE :
+			RTE_CRYPTO_AUTH_OP_VERIFY;
+	auth_xform->iv.offset = IV_OFF;
+	auth_xform->iv.length = vec.iv.len;
+	auth_xform->digest_length = vec.aead.digest.len;
+	auth_xform->key.data = vec.aead.key.val;
+	auth_xform->key.length = vec.aead.key.len;
+
+	cap_idx.algo.auth = auth_xform->algo;
+	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+
+	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
+	if (!cap) {
+		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
+				env.dev_id);
+		return -EINVAL;
+	}
+
+	if (rte_cryptodev_sym_capability_check_auth(cap,
+			auth_xform->key.length,
+			auth_xform->digest_length, 0) != 0) {
+		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
+				info.device_name, auth_xform->key.length,
+				auth_xform->digest_length);
+		return -EPERM;
+	}
+
+	return 0;
+}
+
 static int
 prepare_cmac_xform(struct rte_crypto_sym_xform *xform)
 {
-- 
2.20.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [dpdk-dev] [dpdk-dev v2 1/2] fips_validation: add SGL support
  2020-09-04 16:09   ` [dpdk-dev] [dpdk-dev v2 1/2] fips_validation: add SGL support Fan Zhang
@ 2020-09-07 13:32     ` Suanming Mou
  2020-09-08 10:13       ` Zhang, Roy Fan
  2020-09-17  9:20     ` Griffin, John
  1 sibling, 1 reply; 16+ messages in thread
From: Suanming Mou @ 2020-09-07 13:32 UTC (permalink / raw)
  To: Fan Zhang, dev
  Cc: akhil.goyal, fiona.trahe, arkadiuszx.kusztal, adamx.dybkowski

Hi,

On 9/5/2020 12:09 AM, Fan Zhang wrote:
> This patch adds SGL support to FIPS sample application.
> Originally the application allocates single mbuf of 64KB - 1
> bytes data room. With the change the user may reduce the
> mbuf dataroom size by using the add cmdline option. If the
> input test data is longer than the user provided data room
> size the application will automatically build chained mbufs
> for the target cryptodev PMD to test.
>
> Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
> ---
>   doc/guides/sample_app_ug/fips_validation.rst |   6 +
>   examples/fips_validation/fips_validation.h   |   3 +-
>   examples/fips_validation/main.c              | 377 +++++++++++++------
>   3 files changed, 271 insertions(+), 115 deletions(-)
>
> diff --git a/doc/guides/sample_app_ug/fips_validation.rst b/doc/guides/sample_app_ug/fips_validation.rst
> index 2953fddeb..8d3db2214 100644
> --- a/doc/guides/sample_app_ug/fips_validation.rst
> +++ b/doc/guides/sample_app_ug/fips_validation.rst
> @@ -96,6 +96,7 @@ The application requires a number of command line options:
>            -- --req-file FILE_PATH/FOLDER_PATH
>            --rsp-file FILE_PATH/FOLDER_PATH
>            [--cryptodev DEVICE_NAME] [--cryptodev-id ID] [--path-is-folder]
> +         --mbuf-dataroom DATAROOM_SIZE
>   
>   where,
>     * req-file: The path of the request file or folder, separated by
> @@ -111,6 +112,11 @@ where,
>     * path-is-folder: If presented the application expects req-file and rsp-file
>       are folder paths.
>   
> +  * mbuf-dataroom: By default the application creates mbuf pool with maximum
> +    possible data room (65535 bytes). If the user wants to test scatter-gather
> +    list feature of the PMD he or she may set this value to reduce the dataroom
> +    size so that the input data may be dividied into multiple chained mbufs.
> +
>   
>   To run the application in linux environment to test one AES FIPS test data
>   file for crypto_aesni_mb PMD, issue the command:
> diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
> index 75fa555fa..ecf3d54dd 100644
> --- a/examples/fips_validation/fips_validation.h
> +++ b/examples/fips_validation/fips_validation.h
> @@ -12,7 +12,8 @@
>   #define MAX_CASE_LINE		15
>   #define MAX_LINE_CHAR		204800 /*< max number of characters per line */
>   #define MAX_NB_TESTS		10240
> -#define MAX_BUF_SIZE		2048
> +#define DEF_MBUF_SEG_SIZE	(UINT16_MAX - sizeof(struct rte_mbuf) - \
> +				RTE_PKTMBUF_HEADROOM)
>   #define MAX_STRING_SIZE		64
>   #define MAX_DIGEST_SIZE		64
>   
> diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
> index efd32a86a..fadca6e0c 100644
> --- a/examples/fips_validation/main.c
> +++ b/examples/fips_validation/main.c
> @@ -17,6 +17,7 @@
>   
>   #define REQ_FILE_PATH_KEYWORD	"req-file"
>   #define RSP_FILE_PATH_KEYWORD	"rsp-file"
> +#define MBUF_DATAROOM_KEYWORD	"mbuf-dataroom"
>   #define FOLDER_KEYWORD		"path-is-folder"
>   #define CRYPTODEV_KEYWORD	"cryptodev"
>   #define CRYPTODEV_ID_KEYWORD	"cryptodev-id"
> @@ -33,15 +34,19 @@ struct cryptodev_fips_validate_env {
>   	const char *req_path;
>   	const char *rsp_path;
>   	uint32_t is_path_folder;
> -	uint32_t dev_id;
> +	uint8_t dev_id;
> +	uint8_t dev_support_sgl;
> +	uint16_t mbuf_data_room;
>   	struct rte_mempool *mpool;
>   	struct rte_mempool *sess_mpool;
>   	struct rte_mempool *sess_priv_mpool;
>   	struct rte_mempool *op_pool;
>   	struct rte_mbuf *mbuf;
> +	uint8_t *digest;
> +	uint16_t digest_len;
>   	struct rte_crypto_op *op;
>   	struct rte_cryptodev_sym_session *sess;
> -	uint32_t self_test;
> +	uint16_t self_test;
>   	struct fips_dev_broken_test_config *broken_test_config;
>   } env;
>   
> @@ -50,8 +55,10 @@ cryptodev_fips_validate_app_int(void)
>   {
>   	struct rte_cryptodev_config conf = {rte_socket_id(), 1, 0};
>   	struct rte_cryptodev_qp_conf qp_conf = {128, NULL, NULL};
> +	struct rte_cryptodev_info dev_info;
Better to initialize the dev_info here?
>   	uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(
>   			env.dev_id);
> +	uint32_t nb_mbufs = UINT16_MAX / env.mbuf_data_room + 1;
>   	int ret;
>   
>   	if (env.self_test) {
> @@ -70,8 +77,15 @@ cryptodev_fips_validate_app_int(void)
>   	if (ret < 0)
>   		return ret;
>   
> -	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", 128, 0, 0,
> -			UINT16_MAX, rte_socket_id());
> +	rte_cryptodev_info_get(env.dev_id, &dev_info);
> +	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)
> +		env.dev_support_sgl = 1;
> +	else
> +		env.dev_support_sgl = 0;
> +
> +	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", nb_mbufs,
> +			0, 0, sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM +
> +			env.mbuf_data_room, rte_socket_id());
>   	if (!env.mpool)
>   		return ret;
>   
> @@ -102,10 +116,6 @@ cryptodev_fips_validate_app_int(void)
>   	if (!env.op_pool)
>   		goto error_exit;
>   
> -	env.mbuf = rte_pktmbuf_alloc(env.mpool);
> -	if (!env.mbuf)
> -		goto error_exit;
> -
>   	env.op = rte_crypto_op_alloc(env.op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
>   	if (!env.op)
>   		goto error_exit;
> @@ -160,7 +170,7 @@ parse_cryptodev_arg(char *arg)
>   		return id;
>   	}
>   
> -	env.dev_id = (uint32_t)id;
> +	env.dev_id = (uint8_t)id;
>   
>   	return 0;
>   }
> @@ -191,19 +201,21 @@ parse_cryptodev_id_arg(char *arg)
>   static void
>   cryptodev_fips_validate_usage(const char *prgname)
>   {
> +	uint32_t def_mbuf_seg_size = DEF_MBUF_SEG_SIZE;
>   	printf("%s [EAL options] --\n"
>   		"  --%s: REQUEST-FILE-PATH\n"
>   		"  --%s: RESPONSE-FILE-PATH\n"
>   		"  --%s: indicating both paths are folders\n"
> +		"  --%s: mbuf dataroom size (default %u bytes)\n"
>   		"  --%s: CRYPTODEV-NAME\n"
>   		"  --%s: CRYPTODEV-ID-NAME\n"
>   		"  --%s: self test indicator\n"
>   		"  --%s: self broken test ID\n"
>   		"  --%s: self broken test direction\n",
>   		prgname, REQ_FILE_PATH_KEYWORD, RSP_FILE_PATH_KEYWORD,
> -		FOLDER_KEYWORD, CRYPTODEV_KEYWORD, CRYPTODEV_ID_KEYWORD,
> -		CRYPTODEV_ST_KEYWORD, CRYPTODEV_BK_ID_KEYWORD,
> -		CRYPTODEV_BK_DIR_KEY);
> +		FOLDER_KEYWORD, MBUF_DATAROOM_KEYWORD, def_mbuf_seg_size,
> +		CRYPTODEV_KEYWORD, CRYPTODEV_ID_KEYWORD, CRYPTODEV_ST_KEYWORD,
> +		CRYPTODEV_BK_ID_KEYWORD, CRYPTODEV_BK_DIR_KEY);
>   }
>   
>   static int
> @@ -217,6 +229,7 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
>   			{REQ_FILE_PATH_KEYWORD, required_argument, 0, 0},
>   			{RSP_FILE_PATH_KEYWORD, required_argument, 0, 0},
>   			{FOLDER_KEYWORD, no_argument, 0, 0},
> +			{MBUF_DATAROOM_KEYWORD, required_argument, 0, 0},
>   			{CRYPTODEV_KEYWORD, required_argument, 0, 0},
>   			{CRYPTODEV_ID_KEYWORD, required_argument, 0, 0},
>   			{CRYPTODEV_ST_KEYWORD, no_argument, 0, 0},
> @@ -227,6 +240,14 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
>   
>   	argvopt = argv;
>   
> +	env.mbuf_data_room = DEF_MBUF_SEG_SIZE;
> +	if (rte_cryptodev_count())
> +		env.dev_id = 0;
> +	else {
> +		cryptodev_fips_validate_usage(prgname);
> +		return -EINVAL;
> +	}
> +
>   	while ((opt = getopt_long(argc, argvopt, "s:",
>   				  lgopts, &option_index)) != EOF) {
>   
> @@ -305,6 +326,23 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
>   					cryptodev_fips_validate_usage(prgname);
>   					return -EINVAL;
>   				}
> +			} else if (strcmp(lgopts[option_index].name,
> +					MBUF_DATAROOM_KEYWORD) == 0) {
> +				uint32_t data_room_size;
> +
> +				if (parser_read_uint32(&data_room_size,
> +						optarg) < 0) {
> +					cryptodev_fips_validate_usage(prgname);
> +					return -EINVAL;
> +				}
> +
> +				if (data_room_size == 0 ||
> +						data_room_size > UINT16_MAX) {
> +					cryptodev_fips_validate_usage(prgname);
> +					return -EINVAL;
> +				}
> +
> +				env.mbuf_data_room = data_room_size;
>   			} else {
>   				cryptodev_fips_validate_usage(prgname);
>   				return -EINVAL;
> @@ -315,8 +353,7 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
>   		}
>   	}
>   
> -	if (env.req_path == NULL || env.rsp_path == NULL ||
> -			env.dev_id == UINT32_MAX) {
> +	if (env.req_path == NULL || env.rsp_path == NULL) {
>   		cryptodev_fips_validate_usage(prgname);
>   		return -EINVAL;
>   	}
> @@ -451,60 +488,124 @@ struct fips_test_ops {
>   } test_ops;
>   
>   static int
> -prepare_cipher_op(void)
> +prepare_data_mbufs(struct fips_val *val)
>   {
> -	struct rte_crypto_sym_op *sym = env.op->sym;
> -	uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
> +	struct rte_mbuf *m, *head = 0;
> +	uint8_t *src = val->val;
> +	uint32_t total_len = val->len;
> +	uint16_t nb_seg;
> +	int ret = 0;
>   
> -	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
> -	rte_pktmbuf_reset(env.mbuf);
> -
> -	sym->m_src = env.mbuf;
> -	sym->cipher.data.offset = 0;
> +	if (env.mbuf)
> +		rte_pktmbuf_free(env.mbuf);
>   
> -	memcpy(iv, vec.iv.val, vec.iv.len);
> +	if (total_len > RTE_MBUF_MAX_NB_SEGS) {
> +		RTE_LOG(ERR, USER1, "Data len %u too big\n", total_len);
> +		return -EPERM;
> +	}
>   
> -	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
> -		uint8_t *pt;
> +	nb_seg = total_len / env.mbuf_data_room;
> +	if (total_len % env.mbuf_data_room)
> +		nb_seg++;
>   
> -		if (vec.pt.len > RTE_MBUF_MAX_NB_SEGS) {
> -			RTE_LOG(ERR, USER1, "PT len %u\n", vec.pt.len);
> -			return -EPERM;
> -		}
> +	m = rte_pktmbuf_alloc(env.mpool);
> +	if (!m) {
> +		RTE_LOG(ERR, USER1, "Error %i: Not enough mbuf\n",
> +				-ENOMEM);
> +		return -ENOMEM;
> +	}
> +	head = m;
>   
> -		pt = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.pt.len);
> +	while (nb_seg) {
> +		uint16_t len = RTE_MIN(total_len, env.mbuf_data_room);
> +		uint8_t *dst = (uint8_t *)rte_pktmbuf_append(m, len);
>   
> -		if (!pt) {
> +		if (!dst) {
>   			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
>   					-ENOMEM);
> -			return -ENOMEM;
> +			ret = -ENOMEM;
> +			goto error_exit;
>   		}
>   
> -		memcpy(pt, vec.pt.val, vec.pt.len);
> -		sym->cipher.data.length = vec.pt.len;
> +		memcpy(dst, src, len);
>   
> -	} else {
> -		uint8_t *ct;
> -
> -		if (vec.ct.len > RTE_MBUF_MAX_NB_SEGS) {
> -			RTE_LOG(ERR, USER1, "CT len %u\n", vec.ct.len);
> -			return -EPERM;
> +		if (head != m) {
> +			ret = rte_pktmbuf_chain(head, m);
> +			if (ret) {
> +				rte_pktmbuf_free(m);
> +				RTE_LOG(ERR, USER1, "Error %i: SGL build\n",
> +						ret);
> +				goto error_exit;
> +			}
>   		}
> +		total_len -= len;
>   
> -		ct = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.ct.len);
> +		if (total_len) {
> +			if (!env.dev_support_sgl) {
> +				RTE_LOG(ERR, USER1, "SGL not supported\n");
> +				ret = -EPERM;
> +				goto error_exit;
> +			}
>   
> -		if (!ct) {
> -			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
> -					-ENOMEM);
> -			return -ENOMEM;
> -		}
> +			m = rte_pktmbuf_alloc(env.mpool);
> +			if (!m) {
> +				RTE_LOG(ERR, USER1, "Error %i: No memory\n",
> +						-ENOMEM);
> +				goto error_exit;
> +			}
> +		} else
> +			break;
> +
> +		src += len;
> +		nb_seg--;
> +	}
> +
> +	if (total_len) {
> +		RTE_LOG(ERR, USER1, "Error %i: Failed to store all data\n",
> +				-ENOMEM);
> +		goto error_exit;
> +	}
> +
> +	env.mbuf = head;
> +
> +	return 0;
> +
> +error_exit:
> +	if (head)
> +		rte_pktmbuf_free(head);
> +	return ret;
> +}
> +
> +static int
> +prepare_cipher_op(void)
> +{
> +	struct rte_crypto_sym_op *sym = env.op->sym;
> +	uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
> +	int ret;
> +
> +	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
> +
> +	memcpy(iv, vec.iv.val, vec.iv.len);
> +
> +	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
> +		ret = prepare_data_mbufs(&vec.pt);
> +		if (ret < 0)
> +			return ret;
> +
> +		sym->cipher.data.length = vec.pt.len;
> +	} else {
> +		ret = prepare_data_mbufs(&vec.ct);
> +		if (ret < 0)
> +			return ret;
>   
> -		memcpy(ct, vec.ct.val, vec.ct.len);
>   		sym->cipher.data.length = vec.ct.len;
>   	}
>   
>   	rte_crypto_op_attach_sym_session(env.op, env.sess);
>   
> +	sym->m_src = env.mbuf;
> +	sym->cipher.data.offset = 0;
> +
>   	return 0;
>   }
>   
> @@ -512,32 +613,33 @@ static int
>   prepare_auth_op(void)
>   {
>   	struct rte_crypto_sym_op *sym = env.op->sym;
> -	uint8_t *pt;
> +	int ret;
>   
>   	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
> -	rte_pktmbuf_reset(env.mbuf);
>   
> -	sym->m_src = env.mbuf;
> -	sym->auth.data.offset = 0;
> +	ret = prepare_data_mbufs(&vec.pt);
> +	if (ret < 0)
> +		return ret;
>   
> -	pt = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.pt.len +
> -			vec.cipher_auth.digest.len);
> +	if (env.digest)
> +		rte_free(env.digest);
>   
> -	if (!pt) {
> -		RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
> -				-ENOMEM);
> +	env.digest = rte_zmalloc(NULL, vec.cipher_auth.digest.len,
> +			RTE_CACHE_LINE_SIZE);
> +	if (!env.digest) {
> +		RTE_LOG(ERR, USER1, "Not enough memory\n");
>   		return -ENOMEM;
>   	}
> +	env.digest_len = vec.cipher_auth.digest.len;
>   
> +	sym->m_src = env.mbuf;
> +	sym->auth.data.offset = 0;
>   	sym->auth.data.length = vec.pt.len;
> -	sym->auth.digest.data = pt + vec.pt.len;
> -	sym->auth.digest.phys_addr = rte_pktmbuf_mtophys_offset(
> -			env.mbuf, vec.pt.len);
> -
> -	memcpy(pt, vec.pt.val, vec.pt.len);
> +	sym->auth.digest.data = env.digest;
> +	sym->auth.digest.phys_addr = rte_malloc_virt2iova(env.digest);
>   
>   	if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
> -		memcpy(pt + vec.pt.len, vec.cipher_auth.digest.val,
> +		memcpy(env.digest, vec.cipher_auth.digest.val,
>   				vec.cipher_auth.digest.len);
>   
>   	rte_crypto_op_attach_sym_session(env.op, env.sess);
> @@ -550,65 +652,53 @@ prepare_aead_op(void)
>   {
>   	struct rte_crypto_sym_op *sym = env.op->sym;
>   	uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
> +	int ret;
>   
>   	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
> -	rte_pktmbuf_reset(env.mbuf);
>   
>   	if (info.algo == FIPS_TEST_ALGO_AES_CCM)
> -		memcpy(iv + 1, vec.iv.val, vec.iv.len);
> -	else
> -		memcpy(iv, vec.iv.val, vec.iv.len);
> +		iv++;
>   
> -	sym->m_src = env.mbuf;
> -	sym->aead.data.offset = 0;
> -	sym->aead.aad.data = vec.aead.aad.val;
> -	sym->aead.aad.phys_addr = rte_malloc_virt2iova(sym->aead.aad.data);
> +	if (vec.iv.val)
> +		memcpy(iv, vec.iv.val, vec.iv.len);
> +	else
> +		/* if REQ file has iv length but not data, default as all 0 */
> +		memset(iv, 0, vec.iv.len);
>   
>   	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
> -		uint8_t *pt;
> -
> -		if (vec.pt.len > RTE_MBUF_MAX_NB_SEGS) {
> -			RTE_LOG(ERR, USER1, "PT len %u\n", vec.pt.len);
> -			return -EPERM;
> -		}
> -
> -		pt = (uint8_t *)rte_pktmbuf_append(env.mbuf,
> -				vec.pt.len + vec.aead.digest.len);
> +		ret = prepare_data_mbufs(&vec.pt);
> +		if (ret < 0)
> +			return ret;
>   
> -		if (!pt) {
> -			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
> -					-ENOMEM);
> +		if (env.digest)
> +			rte_free(env.digest);
> +		env.digest = rte_zmalloc(NULL, vec.aead.digest.len,
> +				RTE_CACHE_LINE_SIZE);
> +		if (!env.digest) {
> +			RTE_LOG(ERR, USER1, "Not enough memory\n");
>   			return -ENOMEM;
>   		}
> +		env.digest_len = vec.cipher_auth.digest.len;
>   
> -		memcpy(pt, vec.pt.val, vec.pt.len);
>   		sym->aead.data.length = vec.pt.len;
> -		sym->aead.digest.data = pt + vec.pt.len;
> -		sym->aead.digest.phys_addr = rte_pktmbuf_mtophys_offset(
> -				env.mbuf, vec.pt.len);
> +		sym->aead.digest.data = env.digest;
> +		sym->aead.digest.phys_addr = rte_malloc_virt2iova(env.digest);
>   	} else {
> -		uint8_t *ct;
> -
> -		if (vec.ct.len > RTE_MBUF_MAX_NB_SEGS) {
> -			RTE_LOG(ERR, USER1, "CT len %u\n", vec.ct.len);
> -			return -EPERM;
> -		}
> -
> -		ct = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.ct.len);
> -
> -		if (!ct) {
> -			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
> -					-ENOMEM);
> -			return -ENOMEM;
> -		}
> +		ret = prepare_data_mbufs(&vec.ct);
> +		if (ret < 0)
> +			return ret;
>   
> -		memcpy(ct, vec.ct.val, vec.ct.len);
>   		sym->aead.data.length = vec.ct.len;
>   		sym->aead.digest.data = vec.aead.digest.val;
>   		sym->aead.digest.phys_addr = rte_malloc_virt2iova(
>   				sym->aead.digest.data);
>   	}
>   
> +	sym->m_src = env.mbuf;
> +	sym->aead.data.offset = 0;
> +	sym->aead.aad.data = vec.aead.aad.val;
> +	sym->aead.aad.phys_addr = rte_malloc_virt2iova(sym->aead.aad.data);
> +
>   	rte_crypto_op_attach_sym_session(env.op, env.sess);
>   
>   	return 0;
> @@ -952,11 +1042,48 @@ prepare_xts_xform(struct rte_crypto_sym_xform *xform)
>   	return 0;
>   }
>   
> -static void
> +static int
>   get_writeback_data(struct fips_val *val)
>   {
> -	val->val = rte_pktmbuf_mtod(env.mbuf, uint8_t *);
> -	val->len = rte_pktmbuf_pkt_len(env.mbuf);
> +	struct rte_mbuf *m = env.mbuf;
> +	uint16_t data_len = rte_pktmbuf_pkt_len(m);
> +	uint16_t total_len = data_len + env.digest_len;
> +	uint8_t *src, *dst, *wb_data;
> +
> +	/* in case val is reused for MCT test, try to free the buffer first */
> +	if (val->val) {
> +		free(val->val);
> +		val->val = NULL;
> +	}
> +
> +	wb_data = dst = calloc(1, total_len);
> +	if (!dst) {
> +		RTE_LOG(ERR, USER1, "Error %i: Not enough memory\n", -ENOMEM);
> +		return -ENOMEM;
> +	}
> +
> +	while (m && data_len) {
> +		uint16_t seg_len = RTE_MIN(rte_pktmbuf_data_len(m), data_len);
> +
> +		src = rte_pktmbuf_mtod(m, uint8_t *);
> +		memcpy(dst, src, seg_len);
> +		m = m->next;
> +		data_len -= seg_len;
> +		dst += seg_len;
> +	}
> +
> +	if (data_len) {
> +		RTE_LOG(ERR, USER1, "Error -1: write back data\n");
> +		return -1;
> +	}
> +
> +	if (env.digest)
> +		memcpy(dst, env.digest, env.digest_len);
> +
> +	val->val = wb_data;
> +	val->len = total_len;
> +
> +	return 0;
>   }
>   
>   static int
> @@ -1015,7 +1142,7 @@ fips_run_test(void)
>   static int
>   fips_generic_test(void)
>   {
> -	struct fips_val val;
> +	struct fips_val val = {NULL, 0};
>   	int ret;
>   
>   	fips_test_write_one_case();
> @@ -1030,7 +1157,9 @@ fips_generic_test(void)
>   		return ret;
>   	}
>   
> -	get_writeback_data(&val);
> +	ret = get_writeback_data(&val);
> +	if (ret < 0)
> +		return ret;
>   
>   	switch (info.file_type) {
>   	case FIPS_TYPE_REQ:
> @@ -1051,6 +1180,7 @@ fips_generic_test(void)
>   	}
>   
>   	fprintf(info.fp_wr, "\n");
> +	free(val.val);
>   
>   	return 0;
>   }
> @@ -1061,7 +1191,7 @@ fips_mct_tdes_test(void)
>   #define TDES_BLOCK_SIZE		8
>   #define TDES_EXTERN_ITER	400
>   #define TDES_INTERN_ITER	10000
> -	struct fips_val val, val_key;
> +	struct fips_val val = {NULL, 0}, val_key;
>   	uint8_t prev_out[TDES_BLOCK_SIZE] = {0};
>   	uint8_t prev_prev_out[TDES_BLOCK_SIZE] = {0};
>   	uint8_t prev_in[TDES_BLOCK_SIZE] = {0};
> @@ -1088,7 +1218,9 @@ fips_mct_tdes_test(void)
>   				return ret;
>   			}
>   
> -			get_writeback_data(&val);
> +			ret = get_writeback_data(&val);
> +			if (ret < 0)
> +				return ret;
>   
>   			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
>   				memcpy(prev_in, vec.ct.val, TDES_BLOCK_SIZE);
> @@ -1215,6 +1347,9 @@ fips_mct_tdes_test(void)
>   		}
>   	}
>   
> +	if (val.val)
> +		free(val.val);
> +
>   	return 0;
>   }
>   
> @@ -1224,7 +1359,7 @@ fips_mct_aes_ecb_test(void)
>   #define AES_BLOCK_SIZE	16
>   #define AES_EXTERN_ITER	100
>   #define AES_INTERN_ITER	1000
> -	struct fips_val val, val_key;
> +	struct fips_val val = {NULL, 0}, val_key;
>   	uint8_t prev_out[AES_BLOCK_SIZE] = {0};
>   	uint32_t i, j, k;
>   	int ret;
> @@ -1246,7 +1381,9 @@ fips_mct_aes_ecb_test(void)
>   				return ret;
>   			}
>   
> -			get_writeback_data(&val);
> +			ret = get_writeback_data(&val);
> +			if (ret < 0)
> +				return ret;
>   
>   			if (info.op == FIPS_TEST_ENC_AUTH_GEN)
>   				memcpy(vec.pt.val, val.val, AES_BLOCK_SIZE);
> @@ -1290,6 +1427,9 @@ fips_mct_aes_ecb_test(void)
>   		}
>   	}
>   
> +	if (val.val)
> +		free(val.val);
> +
>   	return 0;
>   }
>   static int
> @@ -1298,7 +1438,7 @@ fips_mct_aes_test(void)
>   #define AES_BLOCK_SIZE	16
>   #define AES_EXTERN_ITER	100
>   #define AES_INTERN_ITER	1000
> -	struct fips_val val, val_key;
> +	struct fips_val val = {NULL, 0}, val_key;
>   	uint8_t prev_out[AES_BLOCK_SIZE] = {0};
>   	uint8_t prev_in[AES_BLOCK_SIZE] = {0};
>   	uint32_t i, j, k;
> @@ -1394,6 +1534,9 @@ fips_mct_aes_test(void)
>   			memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
>   	}
>   
> +	if (val.val)
> +		free(val.val);
> +
>   	return 0;
>   }
>   
> @@ -1403,7 +1546,7 @@ fips_mct_sha_test(void)
>   #define SHA_EXTERN_ITER	100
>   #define SHA_INTERN_ITER	1000
>   #define SHA_MD_BLOCK	3
> -	struct fips_val val, md[SHA_MD_BLOCK];
> +	struct fips_val val = {NULL, 0}, md[SHA_MD_BLOCK];
>   	char temp[MAX_DIGEST_SIZE*2];
>   	int ret;
>   	uint32_t i, j;
> @@ -1477,6 +1620,9 @@ fips_mct_sha_test(void)
>   
>   	rte_free(vec.pt.val);
>   
> +	if (val.val)
> +		free(val.val);
> +
>   	return 0;
>   }
>   
> @@ -1568,7 +1714,6 @@ fips_test_one_file(void)
>   {
>   	int fetch_ret = 0, ret;
>   
> -
>   	ret = init_test_ops();
>   	if (ret < 0) {
>   		RTE_LOG(ERR, USER1, "Error %i: Init test op\n", ret);
> @@ -1616,6 +1761,10 @@ fips_test_one_file(void)
>   
>   	fips_test_clear();
>   
> -	return ret;
> +	if (env.digest)
> +		rte_free(env.digest);
> +	if (env.mbuf)
> +		rte_pktmbuf_free(env.mbuf);
>   
> +	return ret;
>   }



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [dpdk-dev] [dpdk-dev v2 1/2] fips_validation: add SGL support
  2020-09-07 13:32     ` Suanming Mou
@ 2020-09-08 10:13       ` Zhang, Roy Fan
  0 siblings, 0 replies; 16+ messages in thread
From: Zhang, Roy Fan @ 2020-09-08 10:13 UTC (permalink / raw)
  To: Suanming Mou, dev
  Cc: akhil.goyal, Trahe, Fiona, Kusztal, ArkadiuszX, Dybkowski, AdamX

Hi Suanming Mou,

Thanks for the review.

> -----Original Message-----
> From: Suanming Mou <suanmingm@nvidia.com>
> Sent: Monday, September 7, 2020 2:32 PM
> To: Zhang, Roy Fan <roy.fan.zhang@intel.com>; dev@dpdk.org
> Cc: akhil.goyal@nxp.com; Trahe, Fiona <fiona.trahe@intel.com>; Kusztal,
> ArkadiuszX <arkadiuszx.kusztal@intel.com>; Dybkowski, AdamX
> <adamx.dybkowski@intel.com>
> Subject: Re: [dpdk-dev] [dpdk-dev v2 1/2] fips_validation: add SGL support
> 
> Hi,
> 
...
> > @@ -50,8 +55,10 @@ cryptodev_fips_validate_app_int(void)
> >   {
> >   	struct rte_cryptodev_config conf = {rte_socket_id(), 1, 0};
> >   	struct rte_cryptodev_qp_conf qp_conf = {128, NULL, NULL};
> > +	struct rte_cryptodev_info dev_info;
> Better to initialize the dev_info here?

[Fan] dev_info is initialized by rte_cryptodev_info_get() after the device is
successfully configured. So at least we can be sure the device ID is a valid
one and the buffer will be properly set by the driver. Plus the
the implementation of rte_cryptodev_info_get() will do a memset to
the dev_info buffer so it is not necessary to be initialized there.

> >   	uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(
> >   			env.dev_id);
> > +	uint32_t nb_mbufs = UINT16_MAX / env.mbuf_data_room + 1;
> >   	int ret;
> >

Regards,
Fan

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [dpdk-dev] [dpdk-dev v2 2/2] fips_validation: update GCM test
  2020-09-04 16:09   ` [dpdk-dev] [dpdk-dev v2 2/2] fips_validation: update GCM test Fan Zhang
@ 2020-09-17  9:20     ` Griffin, John
  0 siblings, 0 replies; 16+ messages in thread
From: Griffin, John @ 2020-09-17  9:20 UTC (permalink / raw)
  To: Zhang, Roy Fan, dev
  Cc: akhil.goyal, Trahe, Fiona, Kusztal, ArkadiuszX, Dybkowski, AdamX,
	Zhang, Roy Fan, Janjua, Weqaar A



> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Fan Zhang
> Sent: Friday, September 4, 2020 5:10 PM
> To: dev@dpdk.org
> Cc: akhil.goyal@nxp.com; Trahe, Fiona <fiona.trahe@intel.com>; Kusztal,
> ArkadiuszX <arkadiuszx.kusztal@intel.com>; Dybkowski, AdamX
> <adamx.dybkowski@intel.com>; Zhang, Roy Fan <roy.fan.zhang@intel.com>;
> Janjua, Weqaar A <weqaar.a.janjua@intel.com>
> Subject: [dpdk-dev] [dpdk-dev v2 2/2] fips_validation: update GCM test
> 
> This patch updates fips validation GCM test capabilities:
> 
> - In NIST GCMVS spec GMAC test vectors are the GCM ones with plaintext
> length as 0 and uses AAD as input data. Originally fips_validation tests treats
> them both as GCM test vectors.
> This patch introduce automatic test type recognition between the two: when
> plaintext length is 0 the prepare_gmac_xform and prepare_auth_op
> functions are called, otherwise prepare_gcm_xform and prepare_aead_op
> functions are called.
> 
> - NIST GCMVS also specified externally or internally IV generation. When IV is
> to be generated by IUT internally IUT shall store the generated IV in the
> response file. This patch also adds the support to that.
> 
> Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
> Signed-off-by: Weqaar Janjua <Weqaar.A.Janjua@intel.com>
> ---
> --
> 2.20.1

Acked-by: John Griffin <john.griffin@intel.com>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [dpdk-dev] [dpdk-dev v2 1/2] fips_validation: add SGL support
  2020-09-04 16:09   ` [dpdk-dev] [dpdk-dev v2 1/2] fips_validation: add SGL support Fan Zhang
  2020-09-07 13:32     ` Suanming Mou
@ 2020-09-17  9:20     ` Griffin, John
  1 sibling, 0 replies; 16+ messages in thread
From: Griffin, John @ 2020-09-17  9:20 UTC (permalink / raw)
  To: Zhang, Roy Fan, dev
  Cc: akhil.goyal, Trahe, Fiona, Kusztal, ArkadiuszX, Dybkowski, AdamX,
	Zhang, Roy Fan


> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Fan Zhang
> Sent: Friday, September 4, 2020 5:10 PM
> To: dev@dpdk.org
> Cc: akhil.goyal@nxp.com; Trahe, Fiona <fiona.trahe@intel.com>; Kusztal,
> ArkadiuszX <arkadiuszx.kusztal@intel.com>; Dybkowski, AdamX
> <adamx.dybkowski@intel.com>; Zhang, Roy Fan <roy.fan.zhang@intel.com>
> Subject: [dpdk-dev] [dpdk-dev v2 1/2] fips_validation: add SGL support
> 
> This patch adds SGL support to FIPS sample application.
> Originally the application allocates single mbuf of 64KB - 1 bytes data room.
> With the change the user may reduce the mbuf dataroom size by using the
> add cmdline option. If the input test data is longer than the user provided
> data room size the application will automatically build chained mbufs for the
> target cryptodev PMD to test.
> 
> Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
> ---
>  doc/guides/sample_app_ug/fips_validation.rst |   6 +
>  examples/fips_validation/fips_validation.h   |   3 +-
>  examples/fips_validation/main.c              | 377 +++++++++++++------
>  3 files changed, 271 insertions(+), 115 deletions(-)
> 
> --
> 2.20.1

Acked-by: John Griffin <john.griffin@intel.com>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [dpdk-dev] [dpdk-dev v2 0/2] fips_validation: add SGL and GMAC support
  2020-09-04 16:09 ` [dpdk-dev] [dpdk-dev v2 0/2] fips_validation: add SGL and GMAC support Fan Zhang
  2020-09-04 16:09   ` [dpdk-dev] [dpdk-dev v2 1/2] fips_validation: add SGL support Fan Zhang
  2020-09-04 16:09   ` [dpdk-dev] [dpdk-dev v2 2/2] fips_validation: update GCM test Fan Zhang
@ 2020-10-09 18:23   ` Akhil Goyal
  2020-10-09 18:47     ` Zhang, Roy Fan
  2020-10-09 20:08   ` [dpdk-dev] [dpdk-dev v3 " Fan Zhang
  3 siblings, 1 reply; 16+ messages in thread
From: Akhil Goyal @ 2020-10-09 18:23 UTC (permalink / raw)
  To: Fan Zhang, dev; +Cc: fiona.trahe, arkadiuszx.kusztal, adamx.dybkowski

Hi Fan,
> 
> This patchset adds SGL and GMAC support to fips_validation sample
> application. The added cmdline option allows user to split the input
> data into multiple mbuf segments to test SGL feature of the target
> cryptodev PMD; The NIST GCMVS compliant GMAC test method support is also
> added in this patchset.
> 
> V2:
> - Fixed compile issue.
> 
Could you please rebase this patch on TOT of dpdk-next-crypto

I have applied all patches of fips. Just this one is left.

Regards,
Akhil

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [dpdk-dev] [dpdk-dev v2 0/2] fips_validation: add SGL and GMAC support
  2020-10-09 18:23   ` [dpdk-dev] [dpdk-dev v2 0/2] fips_validation: add SGL and GMAC support Akhil Goyal
@ 2020-10-09 18:47     ` Zhang, Roy Fan
  0 siblings, 0 replies; 16+ messages in thread
From: Zhang, Roy Fan @ 2020-10-09 18:47 UTC (permalink / raw)
  To: Akhil Goyal, dev; +Cc: Trahe, Fiona, Kusztal, ArkadiuszX, Dybkowski, AdamX

Hi,

NP.

Regards,
Fan

> -----Original Message-----
> From: Akhil Goyal <akhil.goyal@nxp.com>
> Sent: Friday, October 9, 2020 7:24 PM
> To: Zhang, Roy Fan <roy.fan.zhang@intel.com>; dev@dpdk.org
> Cc: Trahe, Fiona <fiona.trahe@intel.com>; Kusztal, ArkadiuszX
> <arkadiuszx.kusztal@intel.com>; Dybkowski, AdamX
> <adamx.dybkowski@intel.com>
> Subject: RE: [dpdk-dev v2 0/2] fips_validation: add SGL and GMAC support
> 
> Hi Fan,
> >
> > This patchset adds SGL and GMAC support to fips_validation sample
> > application. The added cmdline option allows user to split the input
> > data into multiple mbuf segments to test SGL feature of the target
> > cryptodev PMD; The NIST GCMVS compliant GMAC test method support is
> also
> > added in this patchset.
> >
> > V2:
> > - Fixed compile issue.
> >
> Could you please rebase this patch on TOT of dpdk-next-crypto
> 
> I have applied all patches of fips. Just this one is left.
> 
> Regards,
> Akhil

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [dpdk-dev] [dpdk-dev v3 0/2] fips_validation: add SGL and GMAC support
  2020-09-04 16:09 ` [dpdk-dev] [dpdk-dev v2 0/2] fips_validation: add SGL and GMAC support Fan Zhang
                     ` (2 preceding siblings ...)
  2020-10-09 18:23   ` [dpdk-dev] [dpdk-dev v2 0/2] fips_validation: add SGL and GMAC support Akhil Goyal
@ 2020-10-09 20:08   ` Fan Zhang
  2020-10-09 20:08     ` [dpdk-dev] [dpdk-dev v3 1/2] fips_validation: add SGL support Fan Zhang
  2020-10-09 20:08     ` [dpdk-dev] [dpdk-dev v3 2/2] fips_validation: update GCM test Fan Zhang
  3 siblings, 2 replies; 16+ messages in thread
From: Fan Zhang @ 2020-10-09 20:08 UTC (permalink / raw)
  To: dev; +Cc: akhil.goyal, Fan Zhang

This patchset adds SGL and GMAC support to fips_validation sample
application. The added cmdline option allows user to split the input
data into multiple mbuf segments to test SGL feature of the target
cryptodev PMD; The NIST GCMVS compliant GMAC test method support is also
added in this patchset.

V3:
- Rebased on top of latest master.

V2:
- Fixed compile issue.

Fan Zhang (2):
  fips_validation: add SGL support
  fips_validation: update GCM test

 doc/guides/rel_notes/release_20_11.rst        |   5 +
 doc/guides/sample_app_ug/fips_validation.rst  |   6 +
 examples/fips_validation/fips_validation.h    |  29 +-
 .../fips_validation/fips_validation_gcm.c     | 118 ++++-
 examples/fips_validation/main.c               | 447 +++++++++++++-----
 5 files changed, 460 insertions(+), 145 deletions(-)

-- 
2.20.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [dpdk-dev] [dpdk-dev v3 1/2] fips_validation: add SGL support
  2020-10-09 20:08   ` [dpdk-dev] [dpdk-dev v3 " Fan Zhang
@ 2020-10-09 20:08     ` Fan Zhang
  2020-10-09 20:08     ` [dpdk-dev] [dpdk-dev v3 2/2] fips_validation: update GCM test Fan Zhang
  1 sibling, 0 replies; 16+ messages in thread
From: Fan Zhang @ 2020-10-09 20:08 UTC (permalink / raw)
  To: dev; +Cc: akhil.goyal, Fan Zhang, John Griffin

This patch adds SGL support to FIPS sample application.
Originally the application allocates single mbuf of 64KB - 1
bytes data room. With the change the user may reduce the
mbuf dataroom size by using the add cmdline option. If the
input test data is longer than the user provided data room
size the application will automatically build chained mbufs
for the target cryptodev PMD to test.

Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: John Griffin <john.griffin@intel.com>
---
 doc/guides/sample_app_ug/fips_validation.rst |   6 +
 examples/fips_validation/fips_validation.h   |   3 +-
 examples/fips_validation/main.c              | 382 +++++++++++++------
 3 files changed, 271 insertions(+), 120 deletions(-)

diff --git a/doc/guides/sample_app_ug/fips_validation.rst b/doc/guides/sample_app_ug/fips_validation.rst
index 2953fddeb..8d3db2214 100644
--- a/doc/guides/sample_app_ug/fips_validation.rst
+++ b/doc/guides/sample_app_ug/fips_validation.rst
@@ -96,6 +96,7 @@ The application requires a number of command line options:
          -- --req-file FILE_PATH/FOLDER_PATH
          --rsp-file FILE_PATH/FOLDER_PATH
          [--cryptodev DEVICE_NAME] [--cryptodev-id ID] [--path-is-folder]
+         --mbuf-dataroom DATAROOM_SIZE
 
 where,
   * req-file: The path of the request file or folder, separated by
@@ -111,6 +112,11 @@ where,
   * path-is-folder: If presented the application expects req-file and rsp-file
     are folder paths.
 
+  * mbuf-dataroom: By default the application creates mbuf pool with maximum
+    possible data room (65535 bytes). If the user wants to test scatter-gather
+    list feature of the PMD he or she may set this value to reduce the dataroom
+    size so that the input data may be dividied into multiple chained mbufs.
+
 
 To run the application in linux environment to test one AES FIPS test data
 file for crypto_aesni_mb PMD, issue the command:
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index ca8964aaa..bee85e2da 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -12,7 +12,8 @@
 #define MAX_CASE_LINE		15
 #define MAX_LINE_CHAR		204800 /*< max number of characters per line */
 #define MAX_NB_TESTS		10240
-#define MAX_BUF_SIZE		2048
+#define DEF_MBUF_SEG_SIZE	(UINT16_MAX - sizeof(struct rte_mbuf) - \
+				RTE_PKTMBUF_HEADROOM)
 #define MAX_STRING_SIZE		64
 #define MAX_FILE_NAME_SIZE	256
 #define MAX_DIGEST_SIZE		64
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index 2a7a3fb5e..4d778af11 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -17,6 +17,7 @@
 
 #define REQ_FILE_PATH_KEYWORD	"req-file"
 #define RSP_FILE_PATH_KEYWORD	"rsp-file"
+#define MBUF_DATAROOM_KEYWORD	"mbuf-dataroom"
 #define FOLDER_KEYWORD		"path-is-folder"
 #define CRYPTODEV_KEYWORD	"cryptodev"
 #define CRYPTODEV_ID_KEYWORD	"cryptodev-id"
@@ -33,15 +34,19 @@ struct cryptodev_fips_validate_env {
 	const char *req_path;
 	const char *rsp_path;
 	uint32_t is_path_folder;
-	uint32_t dev_id;
+	uint8_t dev_id;
+	uint8_t dev_support_sgl;
+	uint16_t mbuf_data_room;
 	struct rte_mempool *mpool;
 	struct rte_mempool *sess_mpool;
 	struct rte_mempool *sess_priv_mpool;
 	struct rte_mempool *op_pool;
 	struct rte_mbuf *mbuf;
+	uint8_t *digest;
+	uint16_t digest_len;
 	struct rte_crypto_op *op;
 	struct rte_cryptodev_sym_session *sess;
-	uint32_t self_test;
+	uint16_t self_test;
 	struct fips_dev_broken_test_config *broken_test_config;
 } env;
 
@@ -50,8 +55,10 @@ cryptodev_fips_validate_app_int(void)
 {
 	struct rte_cryptodev_config conf = {rte_socket_id(), 1, 0};
 	struct rte_cryptodev_qp_conf qp_conf = {128, NULL, NULL};
+	struct rte_cryptodev_info dev_info;
 	uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(
 			env.dev_id);
+	uint32_t nb_mbufs = UINT16_MAX / env.mbuf_data_room + 1;
 	int ret;
 
 	if (env.self_test) {
@@ -70,8 +77,15 @@ cryptodev_fips_validate_app_int(void)
 	if (ret < 0)
 		return ret;
 
-	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", 128, 0, 0,
-			UINT16_MAX, rte_socket_id());
+	rte_cryptodev_info_get(env.dev_id, &dev_info);
+	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)
+		env.dev_support_sgl = 1;
+	else
+		env.dev_support_sgl = 0;
+
+	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", nb_mbufs,
+			0, 0, sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM +
+			env.mbuf_data_room, rte_socket_id());
 	if (!env.mpool)
 		return ret;
 
@@ -102,10 +116,6 @@ cryptodev_fips_validate_app_int(void)
 	if (!env.op_pool)
 		goto error_exit;
 
-	env.mbuf = rte_pktmbuf_alloc(env.mpool);
-	if (!env.mbuf)
-		goto error_exit;
-
 	env.op = rte_crypto_op_alloc(env.op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
 	if (!env.op)
 		goto error_exit;
@@ -160,7 +170,7 @@ parse_cryptodev_arg(char *arg)
 		return id;
 	}
 
-	env.dev_id = (uint32_t)id;
+	env.dev_id = (uint8_t)id;
 
 	return 0;
 }
@@ -183,7 +193,7 @@ parse_cryptodev_id_arg(char *arg)
 		return -1;
 	}
 
-	env.dev_id = (uint32_t)cryptodev_id;
+	env.dev_id = (uint8_t)cryptodev_id;
 
 	return 0;
 }
@@ -191,19 +201,21 @@ parse_cryptodev_id_arg(char *arg)
 static void
 cryptodev_fips_validate_usage(const char *prgname)
 {
+	uint32_t def_mbuf_seg_size = DEF_MBUF_SEG_SIZE;
 	printf("%s [EAL options] --\n"
 		"  --%s: REQUEST-FILE-PATH\n"
 		"  --%s: RESPONSE-FILE-PATH\n"
 		"  --%s: indicating both paths are folders\n"
+		"  --%s: mbuf dataroom size (default %u bytes)\n"
 		"  --%s: CRYPTODEV-NAME\n"
 		"  --%s: CRYPTODEV-ID-NAME\n"
 		"  --%s: self test indicator\n"
 		"  --%s: self broken test ID\n"
 		"  --%s: self broken test direction\n",
 		prgname, REQ_FILE_PATH_KEYWORD, RSP_FILE_PATH_KEYWORD,
-		FOLDER_KEYWORD, CRYPTODEV_KEYWORD, CRYPTODEV_ID_KEYWORD,
-		CRYPTODEV_ST_KEYWORD, CRYPTODEV_BK_ID_KEYWORD,
-		CRYPTODEV_BK_DIR_KEY);
+		FOLDER_KEYWORD, MBUF_DATAROOM_KEYWORD, def_mbuf_seg_size,
+		CRYPTODEV_KEYWORD, CRYPTODEV_ID_KEYWORD, CRYPTODEV_ST_KEYWORD,
+		CRYPTODEV_BK_ID_KEYWORD, CRYPTODEV_BK_DIR_KEY);
 }
 
 static int
@@ -217,6 +229,7 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 			{REQ_FILE_PATH_KEYWORD, required_argument, 0, 0},
 			{RSP_FILE_PATH_KEYWORD, required_argument, 0, 0},
 			{FOLDER_KEYWORD, no_argument, 0, 0},
+			{MBUF_DATAROOM_KEYWORD, required_argument, 0, 0},
 			{CRYPTODEV_KEYWORD, required_argument, 0, 0},
 			{CRYPTODEV_ID_KEYWORD, required_argument, 0, 0},
 			{CRYPTODEV_ST_KEYWORD, no_argument, 0, 0},
@@ -227,6 +240,14 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 
 	argvopt = argv;
 
+	env.mbuf_data_room = DEF_MBUF_SEG_SIZE;
+	if (rte_cryptodev_count())
+		env.dev_id = 0;
+	else {
+		cryptodev_fips_validate_usage(prgname);
+		return -EINVAL;
+	}
+
 	while ((opt = getopt_long(argc, argvopt, "s:",
 				  lgopts, &option_index)) != EOF) {
 
@@ -305,6 +326,23 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 					cryptodev_fips_validate_usage(prgname);
 					return -EINVAL;
 				}
+			} else if (strcmp(lgopts[option_index].name,
+					MBUF_DATAROOM_KEYWORD) == 0) {
+				uint32_t data_room_size;
+
+				if (parser_read_uint32(&data_room_size,
+						optarg) < 0) {
+					cryptodev_fips_validate_usage(prgname);
+					return -EINVAL;
+				}
+
+				if (data_room_size == 0 ||
+						data_room_size > UINT16_MAX) {
+					cryptodev_fips_validate_usage(prgname);
+					return -EINVAL;
+				}
+
+				env.mbuf_data_room = data_room_size;
 			} else {
 				cryptodev_fips_validate_usage(prgname);
 				return -EINVAL;
@@ -315,12 +353,6 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 		}
 	}
 
-	if (env.dev_id == UINT32_MAX) {
-		RTE_LOG(ERR, USER1, "No device specified\n");
-		cryptodev_fips_validate_usage(prgname);
-		return -EINVAL;
-	}
-
 	if ((env.req_path == NULL && env.rsp_path != NULL) ||
 			(env.req_path != NULL && env.rsp_path == NULL)) {
 		RTE_LOG(ERR, USER1, "Missing req path or rsp path\n");
@@ -469,60 +501,124 @@ struct fips_test_ops {
 } test_ops;
 
 static int
-prepare_cipher_op(void)
+prepare_data_mbufs(struct fips_val *val)
 {
-	struct rte_crypto_sym_op *sym = env.op->sym;
-	uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
-
-	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
-	rte_pktmbuf_reset(env.mbuf);
+	struct rte_mbuf *m, *head = 0;
+	uint8_t *src = val->val;
+	uint32_t total_len = val->len;
+	uint16_t nb_seg;
+	int ret = 0;
 
-	sym->m_src = env.mbuf;
-	sym->cipher.data.offset = 0;
+	if (env.mbuf)
+		rte_pktmbuf_free(env.mbuf);
 
-	memcpy(iv, vec.iv.val, vec.iv.len);
+	if (total_len > RTE_MBUF_MAX_NB_SEGS) {
+		RTE_LOG(ERR, USER1, "Data len %u too big\n", total_len);
+		return -EPERM;
+	}
 
-	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
-		uint8_t *pt;
+	nb_seg = total_len / env.mbuf_data_room;
+	if (total_len % env.mbuf_data_room)
+		nb_seg++;
 
-		if (vec.pt.len > RTE_MBUF_MAX_NB_SEGS) {
-			RTE_LOG(ERR, USER1, "PT len %u\n", vec.pt.len);
-			return -EPERM;
-		}
+	m = rte_pktmbuf_alloc(env.mpool);
+	if (!m) {
+		RTE_LOG(ERR, USER1, "Error %i: Not enough mbuf\n",
+				-ENOMEM);
+		return -ENOMEM;
+	}
+	head = m;
 
-		pt = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.pt.len);
+	while (nb_seg) {
+		uint16_t len = RTE_MIN(total_len, env.mbuf_data_room);
+		uint8_t *dst = (uint8_t *)rte_pktmbuf_append(m, len);
 
-		if (!pt) {
+		if (!dst) {
 			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
 					-ENOMEM);
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto error_exit;
 		}
 
-		memcpy(pt, vec.pt.val, vec.pt.len);
-		sym->cipher.data.length = vec.pt.len;
-
-	} else {
-		uint8_t *ct;
+		memcpy(dst, src, len);
 
-		if (vec.ct.len > RTE_MBUF_MAX_NB_SEGS) {
-			RTE_LOG(ERR, USER1, "CT len %u\n", vec.ct.len);
-			return -EPERM;
+		if (head != m) {
+			ret = rte_pktmbuf_chain(head, m);
+			if (ret) {
+				rte_pktmbuf_free(m);
+				RTE_LOG(ERR, USER1, "Error %i: SGL build\n",
+						ret);
+				goto error_exit;
+			}
 		}
+		total_len -= len;
 
-		ct = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.ct.len);
+		if (total_len) {
+			if (!env.dev_support_sgl) {
+				RTE_LOG(ERR, USER1, "SGL not supported\n");
+				ret = -EPERM;
+				goto error_exit;
+			}
 
-		if (!ct) {
-			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
-					-ENOMEM);
-			return -ENOMEM;
-		}
+			m = rte_pktmbuf_alloc(env.mpool);
+			if (!m) {
+				RTE_LOG(ERR, USER1, "Error %i: No memory\n",
+						-ENOMEM);
+				goto error_exit;
+			}
+		} else
+			break;
+
+		src += len;
+		nb_seg--;
+	}
+
+	if (total_len) {
+		RTE_LOG(ERR, USER1, "Error %i: Failed to store all data\n",
+				-ENOMEM);
+		goto error_exit;
+	}
+
+	env.mbuf = head;
+
+	return 0;
+
+error_exit:
+	if (head)
+		rte_pktmbuf_free(head);
+	return ret;
+}
+
+static int
+prepare_cipher_op(void)
+{
+	struct rte_crypto_sym_op *sym = env.op->sym;
+	uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
+	int ret;
+
+	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+
+	memcpy(iv, vec.iv.val, vec.iv.len);
+
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+		ret = prepare_data_mbufs(&vec.pt);
+		if (ret < 0)
+			return ret;
+
+		sym->cipher.data.length = vec.pt.len;
+	} else {
+		ret = prepare_data_mbufs(&vec.ct);
+		if (ret < 0)
+			return ret;
 
-		memcpy(ct, vec.ct.val, vec.ct.len);
 		sym->cipher.data.length = vec.ct.len;
 	}
 
 	rte_crypto_op_attach_sym_session(env.op, env.sess);
 
+	sym->m_src = env.mbuf;
+	sym->cipher.data.offset = 0;
+
 	return 0;
 }
 
@@ -530,32 +626,33 @@ static int
 prepare_auth_op(void)
 {
 	struct rte_crypto_sym_op *sym = env.op->sym;
-	uint8_t *pt;
+	int ret;
 
 	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
-	rte_pktmbuf_reset(env.mbuf);
 
-	sym->m_src = env.mbuf;
-	sym->auth.data.offset = 0;
+	ret = prepare_data_mbufs(&vec.pt);
+	if (ret < 0)
+		return ret;
 
-	pt = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.pt.len +
-			vec.cipher_auth.digest.len);
+	if (env.digest)
+		rte_free(env.digest);
 
-	if (!pt) {
-		RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
-				-ENOMEM);
+	env.digest = rte_zmalloc(NULL, vec.cipher_auth.digest.len,
+			RTE_CACHE_LINE_SIZE);
+	if (!env.digest) {
+		RTE_LOG(ERR, USER1, "Not enough memory\n");
 		return -ENOMEM;
 	}
+	env.digest_len = vec.cipher_auth.digest.len;
 
+	sym->m_src = env.mbuf;
+	sym->auth.data.offset = 0;
 	sym->auth.data.length = vec.pt.len;
-	sym->auth.digest.data = pt + vec.pt.len;
-	sym->auth.digest.phys_addr = rte_pktmbuf_iova_offset(
-			env.mbuf, vec.pt.len);
-
-	memcpy(pt, vec.pt.val, vec.pt.len);
+	sym->auth.digest.data = env.digest;
+	sym->auth.digest.phys_addr = rte_malloc_virt2iova(env.digest);
 
 	if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
-		memcpy(pt + vec.pt.len, vec.cipher_auth.digest.val,
+		memcpy(env.digest, vec.cipher_auth.digest.val,
 				vec.cipher_auth.digest.len);
 
 	rte_crypto_op_attach_sym_session(env.op, env.sess);
@@ -568,65 +665,53 @@ prepare_aead_op(void)
 {
 	struct rte_crypto_sym_op *sym = env.op->sym;
 	uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
+	int ret;
 
 	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
-	rte_pktmbuf_reset(env.mbuf);
 
 	if (info.algo == FIPS_TEST_ALGO_AES_CCM)
-		memcpy(iv + 1, vec.iv.val, vec.iv.len);
-	else
-		memcpy(iv, vec.iv.val, vec.iv.len);
+		iv++;
 
-	sym->m_src = env.mbuf;
-	sym->aead.data.offset = 0;
-	sym->aead.aad.data = vec.aead.aad.val;
-	sym->aead.aad.phys_addr = rte_malloc_virt2iova(sym->aead.aad.data);
+	if (vec.iv.val)
+		memcpy(iv, vec.iv.val, vec.iv.len);
+	else
+		/* if REQ file has iv length but not data, default as all 0 */
+		memset(iv, 0, vec.iv.len);
 
 	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
-		uint8_t *pt;
-
-		if (vec.pt.len > RTE_MBUF_MAX_NB_SEGS) {
-			RTE_LOG(ERR, USER1, "PT len %u\n", vec.pt.len);
-			return -EPERM;
-		}
-
-		pt = (uint8_t *)rte_pktmbuf_append(env.mbuf,
-				vec.pt.len + vec.aead.digest.len);
+		ret = prepare_data_mbufs(&vec.pt);
+		if (ret < 0)
+			return ret;
 
-		if (!pt) {
-			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
-					-ENOMEM);
+		if (env.digest)
+			rte_free(env.digest);
+		env.digest = rte_zmalloc(NULL, vec.aead.digest.len,
+				RTE_CACHE_LINE_SIZE);
+		if (!env.digest) {
+			RTE_LOG(ERR, USER1, "Not enough memory\n");
 			return -ENOMEM;
 		}
+		env.digest_len = vec.cipher_auth.digest.len;
 
-		memcpy(pt, vec.pt.val, vec.pt.len);
 		sym->aead.data.length = vec.pt.len;
-		sym->aead.digest.data = pt + vec.pt.len;
-		sym->aead.digest.phys_addr = rte_pktmbuf_iova_offset(
-				env.mbuf, vec.pt.len);
+		sym->aead.digest.data = env.digest;
+		sym->aead.digest.phys_addr = rte_malloc_virt2iova(env.digest);
 	} else {
-		uint8_t *ct;
-
-		if (vec.ct.len > RTE_MBUF_MAX_NB_SEGS) {
-			RTE_LOG(ERR, USER1, "CT len %u\n", vec.ct.len);
-			return -EPERM;
-		}
-
-		ct = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.ct.len);
-
-		if (!ct) {
-			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
-					-ENOMEM);
-			return -ENOMEM;
-		}
+		ret = prepare_data_mbufs(&vec.ct);
+		if (ret < 0)
+			return ret;
 
-		memcpy(ct, vec.ct.val, vec.ct.len);
 		sym->aead.data.length = vec.ct.len;
 		sym->aead.digest.data = vec.aead.digest.val;
 		sym->aead.digest.phys_addr = rte_malloc_virt2iova(
 				sym->aead.digest.data);
 	}
 
+	sym->m_src = env.mbuf;
+	sym->aead.data.offset = 0;
+	sym->aead.aad.data = vec.aead.aad.val;
+	sym->aead.aad.phys_addr = rte_malloc_virt2iova(sym->aead.aad.data);
+
 	rte_crypto_op_attach_sym_session(env.op, env.sess);
 
 	return 0;
@@ -970,11 +1055,48 @@ prepare_xts_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
-static void
+static int
 get_writeback_data(struct fips_val *val)
 {
-	val->val = rte_pktmbuf_mtod(env.mbuf, uint8_t *);
-	val->len = rte_pktmbuf_pkt_len(env.mbuf);
+	struct rte_mbuf *m = env.mbuf;
+	uint16_t data_len = rte_pktmbuf_pkt_len(m);
+	uint16_t total_len = data_len + env.digest_len;
+	uint8_t *src, *dst, *wb_data;
+
+	/* in case val is reused for MCT test, try to free the buffer first */
+	if (val->val) {
+		free(val->val);
+		val->val = NULL;
+	}
+
+	wb_data = dst = calloc(1, total_len);
+	if (!dst) {
+		RTE_LOG(ERR, USER1, "Error %i: Not enough memory\n", -ENOMEM);
+		return -ENOMEM;
+	}
+
+	while (m && data_len) {
+		uint16_t seg_len = RTE_MIN(rte_pktmbuf_data_len(m), data_len);
+
+		src = rte_pktmbuf_mtod(m, uint8_t *);
+		memcpy(dst, src, seg_len);
+		m = m->next;
+		data_len -= seg_len;
+		dst += seg_len;
+	}
+
+	if (data_len) {
+		RTE_LOG(ERR, USER1, "Error -1: write back data\n");
+		return -1;
+	}
+
+	if (env.digest)
+		memcpy(dst, env.digest, env.digest_len);
+
+	val->val = wb_data;
+	val->len = total_len;
+
+	return 0;
 }
 
 static int
@@ -1033,7 +1155,7 @@ fips_run_test(void)
 static int
 fips_generic_test(void)
 {
-	struct fips_val val;
+	struct fips_val val = {NULL, 0};
 	int ret;
 
 	fips_test_write_one_case();
@@ -1048,7 +1170,9 @@ fips_generic_test(void)
 		return ret;
 	}
 
-	get_writeback_data(&val);
+	ret = get_writeback_data(&val);
+	if (ret < 0)
+		return ret;
 
 	switch (info.file_type) {
 	case FIPS_TYPE_REQ:
@@ -1069,6 +1193,7 @@ fips_generic_test(void)
 	}
 
 	fprintf(info.fp_wr, "\n");
+	free(val.val);
 
 	return 0;
 }
@@ -1079,7 +1204,7 @@ fips_mct_tdes_test(void)
 #define TDES_BLOCK_SIZE		8
 #define TDES_EXTERN_ITER	400
 #define TDES_INTERN_ITER	10000
-	struct fips_val val, val_key;
+	struct fips_val val = {NULL, 0}, val_key;
 	uint8_t prev_out[TDES_BLOCK_SIZE] = {0};
 	uint8_t prev_prev_out[TDES_BLOCK_SIZE] = {0};
 	uint8_t prev_in[TDES_BLOCK_SIZE] = {0};
@@ -1108,7 +1233,9 @@ fips_mct_tdes_test(void)
 				return ret;
 			}
 
-			get_writeback_data(&val);
+			ret = get_writeback_data(&val);
+			if (ret < 0)
+				return ret;
 
 			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
 				memcpy(prev_in, vec.ct.val, TDES_BLOCK_SIZE);
@@ -1235,6 +1362,9 @@ fips_mct_tdes_test(void)
 		}
 	}
 
+	if (val.val)
+		free(val.val);
+
 	return 0;
 }
 
@@ -1244,7 +1374,7 @@ fips_mct_aes_ecb_test(void)
 #define AES_BLOCK_SIZE	16
 #define AES_EXTERN_ITER	100
 #define AES_INTERN_ITER	1000
-	struct fips_val val, val_key;
+	struct fips_val val = {NULL, 0}, val_key;
 	uint8_t prev_out[AES_BLOCK_SIZE] = {0};
 	uint32_t i, j, k;
 	int ret;
@@ -1266,7 +1396,9 @@ fips_mct_aes_ecb_test(void)
 				return ret;
 			}
 
-			get_writeback_data(&val);
+			ret = get_writeback_data(&val);
+			if (ret < 0)
+				return ret;
 
 			if (info.op == FIPS_TEST_ENC_AUTH_GEN)
 				memcpy(vec.pt.val, val.val, AES_BLOCK_SIZE);
@@ -1310,6 +1442,9 @@ fips_mct_aes_ecb_test(void)
 		}
 	}
 
+	if (val.val)
+		free(val.val);
+
 	return 0;
 }
 static int
@@ -1318,7 +1453,7 @@ fips_mct_aes_test(void)
 #define AES_BLOCK_SIZE	16
 #define AES_EXTERN_ITER	100
 #define AES_INTERN_ITER	1000
-	struct fips_val val, val_key;
+	struct fips_val val = {NULL, 0}, val_key;
 	uint8_t prev_out[AES_BLOCK_SIZE] = {0};
 	uint8_t prev_in[AES_BLOCK_SIZE] = {0};
 	uint32_t i, j, k;
@@ -1414,6 +1549,9 @@ fips_mct_aes_test(void)
 			memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
 	}
 
+	if (val.val)
+		free(val.val);
+
 	return 0;
 }
 
@@ -1423,7 +1561,7 @@ fips_mct_sha_test(void)
 #define SHA_EXTERN_ITER	100
 #define SHA_INTERN_ITER	1000
 #define SHA_MD_BLOCK	3
-	struct fips_val val, md[SHA_MD_BLOCK];
+	struct fips_val val = {NULL, 0}, md[SHA_MD_BLOCK];
 	char temp[MAX_DIGEST_SIZE*2];
 	int ret;
 	uint32_t i, j;
@@ -1497,6 +1635,9 @@ fips_mct_sha_test(void)
 
 	rte_free(vec.pt.val);
 
+	if (val.val)
+		free(val.val);
+
 	return 0;
 }
 
@@ -1588,7 +1729,6 @@ fips_test_one_file(void)
 {
 	int fetch_ret = 0, ret;
 
-
 	ret = init_test_ops();
 	if (ret < 0) {
 		RTE_LOG(ERR, USER1, "Error %i: Init test op\n", ret);
@@ -1636,6 +1776,10 @@ fips_test_one_file(void)
 
 	fips_test_clear();
 
-	return ret;
+	if (env.digest)
+		rte_free(env.digest);
+	if (env.mbuf)
+		rte_pktmbuf_free(env.mbuf);
 
+	return ret;
 }
-- 
2.20.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [dpdk-dev] [dpdk-dev v3 2/2] fips_validation: update GCM test
  2020-10-09 20:08   ` [dpdk-dev] [dpdk-dev v3 " Fan Zhang
  2020-10-09 20:08     ` [dpdk-dev] [dpdk-dev v3 1/2] fips_validation: add SGL support Fan Zhang
@ 2020-10-09 20:08     ` Fan Zhang
  2020-10-10 16:55       ` Akhil Goyal
  1 sibling, 1 reply; 16+ messages in thread
From: Fan Zhang @ 2020-10-09 20:08 UTC (permalink / raw)
  To: dev; +Cc: akhil.goyal, Fan Zhang, Weqaar Janjua, John Griffin

This patch updates fips validation GCM test capabilities:

- In NIST GCMVS spec GMAC test vectors are the GCM ones with
plaintext length as 0 and uses AAD as input data. Originally
fips_validation tests treats them both as GCM test vectors.
This patch introduce automatic test type recognition between
the two: when plaintext length is 0 the prepare_gmac_xform
and prepare_auth_op functions are called, otherwise
prepare_gcm_xform and prepare_aead_op functions are called.

- NIST GCMVS also specified externally or internally IV
generation. When IV is to be generated by IUT internally IUT
shall store the generated IV in the response file. This patch
also adds the support to that.

Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Signed-off-by: Weqaar Janjua <Weqaar.A.Janjua@intel.com>
Acked-by: John Griffin <john.griffin@intel.com>
---
 doc/guides/rel_notes/release_20_11.rst        |   5 +
 examples/fips_validation/fips_validation.h    |  26 ++++
 .../fips_validation/fips_validation_gcm.c     | 118 ++++++++++++++++--
 examples/fips_validation/main.c               |  65 ++++++++--
 4 files changed, 189 insertions(+), 25 deletions(-)

diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
index 059ea5fca..7441e6ce4 100644
--- a/doc/guides/rel_notes/release_20_11.rst
+++ b/doc/guides/rel_notes/release_20_11.rst
@@ -159,6 +159,11 @@ New Features
   * Extern objects and functions can be plugged into the pipeline.
   * Transaction-oriented table updates.
 
+* **fips_validation sample application enhancement.**
+
+     fips_vadation sample application is added SGL and NIST GCMVS complaint
+     GMAC test method support.
+
 
 Removed Items
 -------------
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index bee85e2da..8396932f9 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -156,6 +156,11 @@ struct sha_interim_data {
 	enum rte_crypto_auth_algorithm algo;
 };
 
+struct gcm_interim_data {
+	uint8_t is_gmac;
+	uint8_t gen_iv;
+};
+
 struct fips_test_interim_info {
 	FILE *fp_rd;
 	FILE *fp_wr;
@@ -175,6 +180,7 @@ struct fips_test_interim_info {
 		struct tdes_interim_data tdes_data;
 		struct ccm_interim_data ccm_data;
 		struct sha_interim_data sha_data;
+		struct gcm_interim_data gcm_data;
 	} interim_info;
 
 	enum fips_test_op op;
@@ -260,4 +266,24 @@ parse_write_hex_str(struct fips_val *src);
 int
 update_info_vec(uint32_t count);
 
+typedef int (*fips_test_one_case_t)(void);
+typedef int (*fips_prepare_op_t)(void);
+typedef int (*fips_prepare_xform_t)(struct rte_crypto_sym_xform *);
+
+struct fips_test_ops {
+	fips_prepare_xform_t prepare_xform;
+	fips_prepare_op_t prepare_op;
+	fips_test_one_case_t test;
+};
+
+extern struct fips_test_ops test_ops;
+
+int prepare_aead_op(void);
+
+int prepare_auth_op(void);
+
+int prepare_gcm_xform(struct rte_crypto_sym_xform *xform);
+
+int prepare_gmac_xform(struct rte_crypto_sym_xform *xform);
+
 #endif
diff --git a/examples/fips_validation/fips_validation_gcm.c b/examples/fips_validation/fips_validation_gcm.c
index 47576e9a3..df3caa267 100644
--- a/examples/fips_validation/fips_validation_gcm.c
+++ b/examples/fips_validation/fips_validation_gcm.c
@@ -7,6 +7,7 @@
 #include <stdio.h>
 
 #include <rte_cryptodev.h>
+#include <rte_malloc.h>
 
 #include "fips_validation.h"
 
@@ -30,22 +31,93 @@
 
 #define OP_ENC_STR	"Encrypt"
 #define OP_DEC_STR	"Decrypt"
+/* External/Internal IV generation, specified in file name, following NIST
+ * GCMVS Section 6.1
+ */
+#define OP_ENC_EXT_STR	"ExtIV"
+#define OP_ENC_INT_STR	"IntIV"
 
 #define NEG_TEST_STR	"FAIL"
 
+/**
+ * GMAC is essentially zero length plaintext and uses AAD as input data.
+ * NIST does not have GMAC specific test vector but using zero length "PTlen"
+ * and uses AAD as input.
+ **/
+static int
+parser_read_gcm_pt_len(const char *key, char *src,
+		__rte_unused struct fips_val *val)
+{
+	int ret = parser_read_uint32_bit_val(key, src, &vec.pt);
+
+	if (ret < 0)
+		return ret;
+
+	if (vec.pt.len == 0) {
+		info.interim_info.gcm_data.is_gmac = 1;
+		test_ops.prepare_op = prepare_auth_op;
+		test_ops.prepare_xform = prepare_gmac_xform;
+	} else {
+		info.interim_info.gcm_data.is_gmac = 0;
+		test_ops.prepare_op = prepare_aead_op;
+		test_ops.prepare_xform = prepare_gcm_xform;
+	}
+
+	return ret;
+}
+
+static int
+parse_gcm_aad_str(const char *key, char *src,
+		__rte_unused struct fips_val *val)
+{
+	/* For GMAC test vector, AAD is treated as input */
+	if (info.interim_info.gcm_data.is_gmac) {
+		vec.pt.len = vec.aead.aad.len;
+		return parse_uint8_known_len_hex_str(key, src, &vec.pt);
+	} else /* gcm */
+		return parse_uint8_known_len_hex_str(key, src, &vec.aead.aad);
+}
+
+static int
+parse_gcm_pt_ct_str(const char *key, char *src, struct fips_val *val)
+{
+	/* According to NIST GCMVS section 6.1, IUT should generate IV data */
+	if (info.interim_info.gcm_data.gen_iv && vec.iv.len) {
+		uint32_t i;
+
+		if (!vec.iv.val) {
+			vec.iv.val = rte_malloc(0, vec.iv.len, 0);
+			if (!vec.iv.val)
+				return -ENOMEM;
+		}
+
+		for (i = 0; i < vec.iv.len; i++) {
+			int random = rand();
+			vec.iv.val[i] = (uint8_t)random;
+		}
+	}
+
+	/* if PTlen == 0, pt or ct will be handled by AAD later */
+	if (info.interim_info.gcm_data.is_gmac)
+		return 0;
+
+	return parse_uint8_known_len_hex_str(key, src, val);
+}
+
 struct fips_test_callback gcm_dec_vectors[] = {
 		{KEY_STR, parse_uint8_known_len_hex_str, &vec.aead.key},
 		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
-		{CT_STR, parse_uint8_known_len_hex_str, &vec.ct},
-		{AAD_STR, parse_uint8_known_len_hex_str, &vec.aead.aad},
+		{CT_STR, parse_gcm_pt_ct_str, &vec.ct},
+		{AAD_STR, parse_gcm_aad_str, &vec.aead.aad},
 		{TAG_STR, parse_uint8_known_len_hex_str,
 				&vec.aead.digest},
 		{NULL, NULL, NULL} /**< end pointer */
 };
+
 struct fips_test_callback gcm_interim_vectors[] = {
 		{KEYLEN_STR, parser_read_uint32_bit_val, &vec.aead.key},
 		{IVLEN_STR, parser_read_uint32_bit_val, &vec.iv},
-		{PTLEN_STR, parser_read_uint32_bit_val, &vec.pt},
+		{PTLEN_STR, parser_read_gcm_pt_len, &vec.pt},
 		{PTLEN_STR, parser_read_uint32_bit_val, &vec.ct},
 		/**< The NIST test vectors use 'PTlen' to denote input text
 		 *  length in case of decrypt & encrypt operations.
@@ -59,8 +131,8 @@ struct fips_test_callback gcm_interim_vectors[] = {
 struct fips_test_callback gcm_enc_vectors[] = {
 		{KEY_STR, parse_uint8_known_len_hex_str, &vec.aead.key},
 		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
-		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
-		{AAD_STR, parse_uint8_known_len_hex_str, &vec.aead.aad},
+		{PT_STR, parse_gcm_pt_ct_str, &vec.pt},
+		{AAD_STR, parse_gcm_aad_str, &vec.aead.aad},
 		{NULL, NULL, NULL} /**< end pointer */
 };
 
@@ -70,12 +142,28 @@ parse_test_gcm_writeback(struct fips_val *val)
 	struct fips_val tmp_val;
 
 	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+		/* According to NIST GCMVS section 6.1, IUT should provide
+		 * generate IV data
+		 */
+		if (info.interim_info.gcm_data.gen_iv) {
+			fprintf(info.fp_wr, "%s", IV_STR);
+			tmp_val.val = vec.iv.val;
+			tmp_val.len = vec.iv.len;
+
+			parse_write_hex_str(&tmp_val);
+			rte_free(vec.iv.val);
+			vec.iv.val = NULL;
+		}
+
 		fprintf(info.fp_wr, "%s", CT_STR);
 
-		tmp_val.val = val->val;
-		tmp_val.len = vec.pt.len;
+		if (!info.interim_info.gcm_data.is_gmac) {
+			tmp_val.val = val->val;
+			tmp_val.len = vec.pt.len;
 
-		parse_write_hex_str(&tmp_val);
+			parse_write_hex_str(&tmp_val);
+		} else
+			fprintf(info.fp_wr, "\n");
 
 		fprintf(info.fp_wr, "%s", TAG_STR);
 
@@ -86,11 +174,14 @@ parse_test_gcm_writeback(struct fips_val *val)
 	} else {
 		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS) {
 			fprintf(info.fp_wr, "%s", PT_STR);
+			if (!info.interim_info.gcm_data.is_gmac) {
+				fprintf(info.fp_wr, "%s", PT_STR);
+				tmp_val.val = val->val;
+				tmp_val.len = vec.pt.len;
 
-			tmp_val.val = val->val;
-			tmp_val.len = vec.pt.len;
-
-			parse_write_hex_str(&tmp_val);
+				parse_write_hex_str(&tmp_val);
+			} else
+				fprintf(info.fp_wr, "\n");
 		} else
 			fprintf(info.fp_wr, "%s\n", NEG_TEST_STR);
 	}
@@ -108,12 +199,13 @@ parse_test_gcm_init(void)
 	for (i = 0; i < info.nb_vec_lines; i++) {
 		char *line = info.vec[i];
 
-
 		tmp = strstr(line, OP_STR);
 		if (tmp) {
 			if (strstr(line, OP_ENC_STR)) {
 				info.op = FIPS_TEST_ENC_AUTH_GEN;
 				info.callbacks = gcm_enc_vectors;
+				if (strstr(info.file_name, OP_ENC_INT_STR))
+					info.interim_info.gcm_data.gen_iv = 1;
 			} else if (strstr(line, OP_DEC_STR)) {
 				info.op = FIPS_TEST_DEC_AUTH_VERIF;
 				info.callbacks = gcm_dec_vectors;
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index 4d778af11..07532c956 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -490,15 +490,7 @@ main(int argc, char *argv[])
 #define IV_OFF (sizeof(struct rte_crypto_op) + sizeof(struct rte_crypto_sym_op))
 #define CRYPTODEV_FIPS_MAX_RETRIES	16
 
-typedef int (*fips_test_one_case_t)(void);
-typedef int (*fips_prepare_op_t)(void);
-typedef int (*fips_prepare_xform_t)(struct rte_crypto_sym_xform *);
-
-struct fips_test_ops {
-	fips_prepare_xform_t prepare_xform;
-	fips_prepare_op_t prepare_op;
-	fips_test_one_case_t test;
-} test_ops;
+struct fips_test_ops test_ops;
 
 static int
 prepare_data_mbufs(struct fips_val *val)
@@ -622,7 +614,7 @@ prepare_cipher_op(void)
 	return 0;
 }
 
-static int
+int
 prepare_auth_op(void)
 {
 	struct rte_crypto_sym_op *sym = env.op->sym;
@@ -630,6 +622,14 @@ prepare_auth_op(void)
 
 	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
 
+	if (vec.iv.len) {
+		uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *,
+				IV_OFF);
+		memset(iv, 0, vec.iv.len);
+		if (vec.iv.val)
+			memcpy(iv, vec.iv.val, vec.iv.len);
+	}
+
 	ret = prepare_data_mbufs(&vec.pt);
 	if (ret < 0)
 		return ret;
@@ -660,7 +660,7 @@ prepare_auth_op(void)
 	return 0;
 }
 
-static int
+int
 prepare_aead_op(void)
 {
 	struct rte_crypto_sym_op *sym = env.op->sym;
@@ -850,7 +850,7 @@ prepare_hmac_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
-static int
+int
 prepare_gcm_xform(struct rte_crypto_sym_xform *xform)
 {
 	const struct rte_cryptodev_symmetric_capability *cap;
@@ -896,6 +896,47 @@ prepare_gcm_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+int
+prepare_gmac_xform(struct rte_crypto_sym_xform *xform)
+{
+	const struct rte_cryptodev_symmetric_capability *cap;
+	struct rte_cryptodev_sym_capability_idx cap_idx;
+	struct rte_crypto_auth_xform *auth_xform = &xform->auth;
+
+	xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
+
+	auth_xform->algo = RTE_CRYPTO_AUTH_AES_GMAC;
+	auth_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_AUTH_OP_GENERATE :
+			RTE_CRYPTO_AUTH_OP_VERIFY;
+	auth_xform->iv.offset = IV_OFF;
+	auth_xform->iv.length = vec.iv.len;
+	auth_xform->digest_length = vec.aead.digest.len;
+	auth_xform->key.data = vec.aead.key.val;
+	auth_xform->key.length = vec.aead.key.len;
+
+	cap_idx.algo.auth = auth_xform->algo;
+	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+
+	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
+	if (!cap) {
+		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
+				env.dev_id);
+		return -EINVAL;
+	}
+
+	if (rte_cryptodev_sym_capability_check_auth(cap,
+			auth_xform->key.length,
+			auth_xform->digest_length, 0) != 0) {
+		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
+				info.device_name, auth_xform->key.length,
+				auth_xform->digest_length);
+		return -EPERM;
+	}
+
+	return 0;
+}
+
 static int
 prepare_cmac_xform(struct rte_crypto_sym_xform *xform)
 {
-- 
2.20.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [dpdk-dev] [dpdk-dev v3 2/2] fips_validation: update GCM test
  2020-10-09 20:08     ` [dpdk-dev] [dpdk-dev v3 2/2] fips_validation: update GCM test Fan Zhang
@ 2020-10-10 16:55       ` Akhil Goyal
  0 siblings, 0 replies; 16+ messages in thread
From: Akhil Goyal @ 2020-10-10 16:55 UTC (permalink / raw)
  To: Fan Zhang, dev; +Cc: Weqaar Janjua, John Griffin

> This patch updates fips validation GCM test capabilities:
> 
> - In NIST GCMVS spec GMAC test vectors are the GCM ones with
> plaintext length as 0 and uses AAD as input data. Originally
> fips_validation tests treats them both as GCM test vectors.
> This patch introduce automatic test type recognition between
> the two: when plaintext length is 0 the prepare_gmac_xform
> and prepare_auth_op functions are called, otherwise
> prepare_gcm_xform and prepare_aead_op functions are called.
> 
> - NIST GCMVS also specified externally or internally IV
> generation. When IV is to be generated by IUT internally IUT
> shall store the generated IV in the response file. This patch
> also adds the support to that.
> 
> Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
> Signed-off-by: Weqaar Janjua <Weqaar.A.Janjua@intel.com>
> Acked-by: John Griffin <john.griffin@intel.com>
> ---
>  doc/guides/rel_notes/release_20_11.rst        |   5 +
>  examples/fips_validation/fips_validation.h    |  26 ++++
>  .../fips_validation/fips_validation_gcm.c     | 118 ++++++++++++++++--
>  examples/fips_validation/main.c               |  65 ++++++++--
>  4 files changed, 189 insertions(+), 25 deletions(-)
> 
> diff --git a/doc/guides/rel_notes/release_20_11.rst
> b/doc/guides/rel_notes/release_20_11.rst
> index 059ea5fca..7441e6ce4 100644
> --- a/doc/guides/rel_notes/release_20_11.rst
> +++ b/doc/guides/rel_notes/release_20_11.rst
> @@ -159,6 +159,11 @@ New Features
>    * Extern objects and functions can be plugged into the pipeline.
>    * Transaction-oriented table updates.
> 
> +* **fips_validation sample application enhancement.**
> +
> +     fips_vadation sample application is added SGL and NIST GCMVS complaint
> +     GMAC test method support.
> +
> 
These release notes need to be split into two for both the patches in the list. 
I did it while applying the patches.

Series Applied to dpdk-next-crypto

Thanks.

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2020-10-10 16:55 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-18 12:17 [dpdk-dev] [dpdk-dev 0/2] fips_validation: add SGL and GMAC support Fan Zhang
2020-08-18 12:17 ` [dpdk-dev] [dpdk-dev 1/2] fips_validation: add SGL support Fan Zhang
2020-08-18 12:17 ` [dpdk-dev] [dpdk-dev 2/2] fips_validation: update GCM test Fan Zhang
2020-09-04 16:09 ` [dpdk-dev] [dpdk-dev v2 0/2] fips_validation: add SGL and GMAC support Fan Zhang
2020-09-04 16:09   ` [dpdk-dev] [dpdk-dev v2 1/2] fips_validation: add SGL support Fan Zhang
2020-09-07 13:32     ` Suanming Mou
2020-09-08 10:13       ` Zhang, Roy Fan
2020-09-17  9:20     ` Griffin, John
2020-09-04 16:09   ` [dpdk-dev] [dpdk-dev v2 2/2] fips_validation: update GCM test Fan Zhang
2020-09-17  9:20     ` Griffin, John
2020-10-09 18:23   ` [dpdk-dev] [dpdk-dev v2 0/2] fips_validation: add SGL and GMAC support Akhil Goyal
2020-10-09 18:47     ` Zhang, Roy Fan
2020-10-09 20:08   ` [dpdk-dev] [dpdk-dev v3 " Fan Zhang
2020-10-09 20:08     ` [dpdk-dev] [dpdk-dev v3 1/2] fips_validation: add SGL support Fan Zhang
2020-10-09 20:08     ` [dpdk-dev] [dpdk-dev v3 2/2] fips_validation: update GCM test Fan Zhang
2020-10-10 16:55       ` Akhil Goyal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).