DPDK patches and discussions
 help / color / mirror / Atom feed
From: Brian Dooley <brian.dooley@intel.com>
To: dev@dpdk.org
Cc: gakhil@marvell.com, gmuthukrishn@marvell.com,
	Brian Dooley <brian.dooley@intel.com>,
	Fan Zhang <roy.fan.zhang@intel.com>
Subject: [RFC] examples/fips_validation: add fips 140-3 acvp aes-cbc test
Date: Fri, 20 May 2022 16:05:53 +0000	[thread overview]
Message-ID: <20220520160554.495317-1-brian.dooley@intel.com> (raw)

This RFC patch showcases an alternative approach to enable
FIPS 140-3 support in the DPDK fips_validation sample application.

The approach presented here takes advantage of an existing open source
library, libacvp,(https://github.com/cisco/libacvp) to generate the
parsed test cases instead of creating and maintaining a DPDK FIPS
test file parser. In addition call back functions are added to the
dpdk-fips_validation application to process the parsed test vectors
and write back the results.

This initial RFC patch contains the code to parse the FIPS 140-3
test files with libacvp library, and the AES-CBC test runner
callback function implementation with most test types covered
apart from MCT test.

Although a different approach has been proposed
(http://patches.dpdk.org/project/dpdk/list/?series=22738),
it has the disadvantage of having to maintain the parsing code.

For the sake of this RFC here is some information on how to
modify and run a test case.

The libacvp library can be installed by following the Building
instructions in the README of the libacvp repo as linked above.

An example test vector which we can call as our input.req:
https://github.com/cisco/libacvp/blob/main/test/json/aes/aes.json

The header acvVersion metadata at the start needs to been updated
to the following:

    {
      "acvVersion": "1.0",
      "jwt": "NA",
      "url": "NA",
      "isSample": false,
      "vectorSetUrls": ["NA"]
    }

With this RFC patch applied you can then run the dpdk-fips_validation
as follows:

    ./dpdk-fips_validation --vdev=crypto_aesni_mb -- \
        --req-file input.req --rsp-file output.rsp --acvp

Please note the MCT tests in the input.req file will generate an
incorrect result set as the IV update part has yet to be implemented.
This will be addressed in next revision.

Signed-off-by: Brian Dooley <brian.dooley@intel.com>
---
 examples/fips_validation/fips_test_acvp.c  | 183 +++++++++++++++++++++
 examples/fips_validation/fips_validation.h |  34 ++++
 examples/fips_validation/main.c            |  59 ++++---
 examples/fips_validation/meson.build       |   9 +
 4 files changed, 260 insertions(+), 25 deletions(-)
 create mode 100644 examples/fips_validation/fips_test_acvp.c

diff --git a/examples/fips_validation/fips_test_acvp.c b/examples/fips_validation/fips_test_acvp.c
new file mode 100644
index 0000000000..55f6b35a7d
--- /dev/null
+++ b/examples/fips_validation/fips_test_acvp.c
@@ -0,0 +1,183 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <acvp/acvp.h>
+#include <intel-ipsec-mb.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <rte_cryptodev.h>
+#include <rte_malloc.h>
+
+#include "fips_validation.h"
+
+#define IV_OFF (sizeof(struct rte_crypto_op) + sizeof(struct rte_crypto_sym_op))
+
+static ACVP_RESULT logger(char *msg)
+{
+	printf("%s", msg);
+	return ACVP_SUCCESS;
+}
+
+static int aes_cbc_handler(ACVP_TEST_CASE *test_case)
+{
+	ACVP_SYM_CIPHER_TC *tc;
+	struct rte_crypto_sym_xform xform = { 0 };
+	const struct rte_cryptodev_symmetric_capability *cap;
+	struct rte_cryptodev_sym_capability_idx cap_idx;
+	struct rte_crypto_cipher_xform *cipher_xform = &xform.cipher;
+	struct rte_crypto_sym_op *sym = env.op->sym;
+	struct fips_val val = {NULL, 0};
+	uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF);
+	uint16_t n_deqd;
+	int ret;
+
+	memset(&xform, 0, sizeof(xform));
+
+	tc = test_case->tc.symmetric;
+
+	xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+
+	cipher_xform->algo = RTE_CRYPTO_CIPHER_AES_CBC;
+	cipher_xform->op = (tc->direction == ACVP_SYM_CIPH_DIR_ENCRYPT) ?
+		RTE_CRYPTO_AEAD_OP_ENCRYPT :
+		RTE_CRYPTO_AEAD_OP_DECRYPT;
+	cipher_xform->key.data = tc->key;
+	/* Check support for 128 bit key*/
+	if (tc->key_len % 8 == 0)
+		cipher_xform->key.length = 16;
+	else
+		cipher_xform->key.length = tc->key_len;
+
+	if (cipher_xform->algo == RTE_CRYPTO_CIPHER_AES_CBC) {
+		cipher_xform->iv.length = tc->iv_len;
+		cipher_xform->iv.offset = IV_OFF;
+	} else {
+		cipher_xform->iv.length = 0;
+		cipher_xform->iv.offset = 0;
+	}
+	cap_idx.algo.cipher = cipher_xform->algo;
+	cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+
+	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_cipher(cap,
+			cipher_xform->key.length,
+			cipher_xform->iv.length) != 0) {
+		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
+				info.device_name, cipher_xform->key.length,
+				cipher_xform->iv.length);
+		return -EPERM;
+	}
+
+	env.sess = rte_cryptodev_sym_session_create(env.sess_mpool);
+	if (!env.sess)
+		return -ENOMEM;
+
+	ret = rte_cryptodev_sym_session_init(env.dev_id, env.sess, &xform,
+	env.sess_priv_mpool);
+	if (ret < 0) {
+		RTE_LOG(ERR, PMD, "Error %i: Init session\n", ret);
+		return ret;
+	}
+
+	if (env.op)
+		rte_crypto_op_free(env.op);
+
+	env.op = rte_crypto_op_alloc(env.op_pool,
+			RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+	if (!env.op)
+		ret = -ENOMEM;
+
+	memcpy(iv, tc->iv, tc->iv_len);
+
+	if (tc->direction == ACVP_SYM_CIPH_DIR_ENCRYPT) {
+		val.val = tc->pt;
+		val.len = tc->pt_len;
+	} else { /* Decrypt */
+		val.val = tc->ct;
+		val.len = tc->ct_len;
+	}
+
+	ret = prepare_data_mbufs(&val);
+	if (ret < 0)
+		return ret;
+
+	if (tc->direction == ACVP_SYM_CIPH_DIR_ENCRYPT) {
+		sym->cipher.data.length = tc->pt_len;
+	} else { /* Decrypt */
+		sym->cipher.data.length = tc->ct_len;
+	}
+
+	rte_crypto_op_attach_sym_session(env.op, env.sess);
+
+	sym->m_src = env.mbuf;
+	sym->cipher.data.offset = 0;
+
+	if (rte_cryptodev_enqueue_burst(env.dev_id, 0, &env.op, 1) < 1) {
+		RTE_LOG(ERR, USER1, "Error: Failed enqueue\n");
+		return ret = -1;
+	}
+
+	do {
+		struct rte_crypto_op *deqd_op[1];
+
+		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, deqd_op,
+				1);
+	} while (n_deqd == 0);
+
+	rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
+	rte_cryptodev_sym_session_free(env.sess);
+
+	val.val = NULL;
+
+	ret = get_writeback_data(&val);
+	if (ret < 0)
+		return ret;
+
+	if (tc->direction == ACVP_SYM_CIPH_DIR_ENCRYPT) {
+		memcpy(tc->ct, val.val, val.len);
+		tc->ct_len = val.len;
+	} else { /* Decrypt */
+		memcpy(tc->pt, val.val, val.len);
+		tc->pt_len = val.len;
+	}
+
+	return ret;
+}
+
+int
+fips_test_acvp_init(void **acvp_ctx)
+{
+	*acvp_ctx = NULL;
+	ACVP_RESULT acvp_ret = ACVP_SUCCESS;
+
+	/* Create test session and enable CBC tests */
+	acvp_ret = acvp_create_test_session((ACVP_CTX **)acvp_ctx, logger,
+					ACVP_LOG_LVL_INFO);
+	if (acvp_ret != ACVP_SUCCESS)
+		return acvp_ret;
+
+	if (acvp_cap_sym_cipher_enable((ACVP_CTX *)*acvp_ctx, ACVP_AES_CBC,
+				&aes_cbc_handler) != ACVP_SUCCESS)
+		return acvp_ret;
+
+	return ACVP_SUCCESS;
+}
+
+void
+fips_test_acvp(void *acvp_ctx, const char *req_file_path,
+			const char *rsp_file_path)
+{
+	/* Parse request file, run crypto tests and write out response file */
+	acvp_run_vectors_from_file(acvp_ctx, req_file_path, rsp_file_path);
+}
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index aaadf01ba8..de831fd0aa 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -193,8 +193,31 @@ struct fips_test_interim_info {
 	post_prcess_t kat_check;
 };
 
+struct cryptodev_fips_validate_env {
+	const char *req_path;
+	const char *rsp_path;
+	uint32_t is_path_folder;
+	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;
+	uint16_t self_test;
+	struct fips_dev_broken_test_config *broken_test_config;
+	uint8_t is_acvp;
+	void *acvp_ctx;
+};
+
 extern struct fips_test_vector vec;
 extern struct fips_test_interim_info info;
+extern struct cryptodev_fips_validate_env env;
 
 int
 fips_test_init(const char *req_file_path, const char *rsp_file_path,
@@ -289,4 +312,15 @@ int prepare_gcm_xform(struct rte_crypto_sym_xform *xform);
 
 int prepare_gmac_xform(struct rte_crypto_sym_xform *xform);
 
+int prepare_data_mbufs(struct fips_val *val);
+
+int get_writeback_data(struct fips_val *val);
+
+__rte_weak void
+fips_test_acvp(void *acvp_ctx, const char *req_file_path,
+				const char *rsp_file_path);
+
+__rte_weak int
+fips_test_acvp_init(void **acvp_ctx);
+
 #endif
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index e06ae37567..54b45dcc1f 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -12,6 +12,8 @@
 #include <rte_mbuf.h>
 #include <rte_string_fns.h>
 
+#include <acvp/acvp.h>
+
 #include "fips_validation.h"
 #include "fips_dev_self_test.h"
 
@@ -34,30 +36,13 @@ enum {
 	OPT_CRYPTODEV_BK_ID_NUM,
 #define OPT_CRYPTODEV_BK_DIR_KEY    "broken-test-dir"
 	OPT_CRYPTODEV_BK_DIR_KEY_NUM,
+#define OPT_CRYPTODEV_ACVP			"acvp"
+	OPT_CRYPTODEV_ACVP_NUM,
 };
 
 struct fips_test_vector vec;
 struct fips_test_interim_info info;
-
-struct cryptodev_fips_validate_env {
-	const char *req_path;
-	const char *rsp_path;
-	uint32_t is_path_folder;
-	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;
-	uint16_t self_test;
-	struct fips_dev_broken_test_config *broken_test_config;
-} env;
+struct cryptodev_fips_validate_env env;
 
 static int
 cryptodev_fips_validate_app_int(void)
@@ -79,6 +64,12 @@ cryptodev_fips_validate_app_int(void)
 		}
 	}
 
+	if (env.is_acvp) {
+		ret = fips_test_acvp_init(&env.acvp_ctx);
+		if (ret < 0)
+			return ret;
+	}
+
 	ret = rte_cryptodev_configure(env.dev_id, &conf);
 	if (ret < 0)
 		return ret;
@@ -161,6 +152,7 @@ cryptodev_fips_validate_app_uninit(void)
 	rte_mempool_free(env.sess_mpool);
 	rte_mempool_free(env.sess_priv_mpool);
 	rte_mempool_free(env.op_pool);
+	acvp_free_test_session(env.acvp_ctx);
 }
 
 static int
@@ -218,11 +210,13 @@ cryptodev_fips_validate_usage(const char *prgname)
 		"  --%s: CRYPTODEV-ID-NAME\n"
 		"  --%s: self test indicator\n"
 		"  --%s: self broken test ID\n"
-		"  --%s: self broken test direction\n",
+		"  --%s: self broken test direction\n"
+		"  --%s: acvp test indicator\n",
 		prgname, OPT_REQ_FILE_PATH, OPT_RSP_FILE_PATH,
 		OPT_FOLDER, OPT_MBUF_DATAROOM, def_mbuf_seg_size,
 		OPT_CRYPTODEV, OPT_CRYPTODEV_ID, OPT_CRYPTODEV_ST,
-		OPT_CRYPTODEV_BK_ID, OPT_CRYPTODEV_BK_DIR_KEY);
+		OPT_CRYPTODEV_BK_ID, OPT_CRYPTODEV_BK_DIR_KEY,
+		OPT_CRYPTODEV_ACVP);
 }
 
 static int
@@ -251,6 +245,8 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 				NULL, OPT_CRYPTODEV_BK_ID_NUM},
 		{OPT_CRYPTODEV_BK_DIR_KEY, required_argument,
 				NULL, OPT_CRYPTODEV_BK_DIR_KEY_NUM},
+		{OPT_CRYPTODEV_ACVP, no_argument,
+				NULL, OPT_CRYPTODEV_ACVP_NUM},
 		{NULL, 0, 0, 0}
 	};
 
@@ -363,6 +359,10 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 			}
 			break;
 
+		case OPT_CRYPTODEV_ACVP_NUM:
+			env.is_acvp = 1;
+			break;
+
 		default:
 			cryptodev_fips_validate_usage(prgname);
 			return -EINVAL;
@@ -417,6 +417,11 @@ main(int argc, char *argv[])
 	if (!env.is_path_folder) {
 		printf("Processing file %s... ", env.req_path);
 
+		if (env.is_acvp) {
+			fips_test_acvp(env.acvp_ctx, env.req_path, env.rsp_path);
+			printf("Done\n");
+			goto exit;
+		}
 		ret = fips_test_init(env.req_path, env.rsp_path,
 			rte_cryptodev_name_get(env.dev_id));
 		if (ret < 0) {
@@ -425,7 +430,6 @@ main(int argc, char *argv[])
 			goto exit;
 		}
 
-
 		ret = fips_test_one_file();
 		if (ret < 0) {
 			RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
@@ -473,6 +477,11 @@ main(int argc, char *argv[])
 
 			printf("Processing file %s... ", req_path);
 
+			if (env.is_acvp) {
+				fips_test_acvp(env.acvp_ctx, env.req_path, env.rsp_path);
+				continue;
+			}
+
 			ret = fips_test_init(req_path, rsp_path,
 			rte_cryptodev_name_get(env.dev_id));
 			if (ret < 0) {
@@ -511,7 +520,7 @@ main(int argc, char *argv[])
 
 struct fips_test_ops test_ops;
 
-static int
+int
 prepare_data_mbufs(struct fips_val *val)
 {
 	struct rte_mbuf *m, *head = 0;
@@ -1115,7 +1124,7 @@ prepare_xts_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
-static int
+int
 get_writeback_data(struct fips_val *val)
 {
 	struct rte_mbuf *m = env.mbuf;
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
index 7eef456318..03302fcc5a 100644
--- a/examples/fips_validation/meson.build
+++ b/examples/fips_validation/meson.build
@@ -19,5 +19,14 @@ sources = files(
         'fips_validation_sha.c',
         'fips_validation_xts.c',
         'fips_dev_self_test.c',
+        'fips_test_acvp.c',
         'main.c',
 )
+
+libacvp = cc.find_library('acvp', required: true)
+
+if not libacvp.found()
+    libacvp = false
+endif
+
+ext_deps += libacvp
-- 
2.25.1


             reply	other threads:[~2022-05-20 16:09 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-20 16:05 Brian Dooley [this message]
2022-05-25 10:04 ` [EXT] " Gowrishankar Muthukrishnan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220520160554.495317-1-brian.dooley@intel.com \
    --to=brian.dooley@intel.com \
    --cc=dev@dpdk.org \
    --cc=gakhil@marvell.com \
    --cc=gmuthukrishn@marvell.com \
    --cc=roy.fan.zhang@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).