DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH v4 0/8] FIPS validation capability
@ 2018-10-12 14:44 Marko Kovacevic
  2018-10-12 14:44 ` [dpdk-dev] [PATCH v4 1/8] examples: add fips validation into examples Marko Kovacevic
                   ` (10 more replies)
  0 siblings, 11 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-12 14:44 UTC (permalink / raw)
  To: dev; +Cc: roy.fan.zhang, akhil.goyal, arkadiuszx.kusztal, Marko Kovacevic

This sample application is made for the purpose so that users of DPDK
who wish to get FIPS certification for their platforms, this sample app enables
users to parse test vectors that is gotten from NIST and be able to get
a generated response file which they can then verify and be sure their
system will pass FIPS certification.

Marko Kovacevic (8):
v4:
- Added Limitation
- Changed TDES BLOCK SIZE from 16 -> 8
  as DES block size is 64bits (main.c)
v3:
- Fixed a no-testing bug
- Fixed some code style issue

v2:
- Refactor the code.
- Move the code from test to sample applcation

  examples: add fips validation into examples
  examples: add aes parser and enablement for test types
  examples: add hmac parser
  examples: add TDES parser and enablement for test types
  examples: add gcm parser
  examples: add cmac parser and enablement for test types
  examples: add ccm parser and enablement for test types
  doc: add guides for fips validation

 doc/guides/rel_notes/release_18_11.rst             |    6 +
 doc/guides/sample_app_ug/fips_validation.rst       |  105 ++
 doc/guides/sample_app_ug/index.rst                 |    1 +
 examples/cryptodev_fips_validate/Makefile          |   75 ++
 .../cryptodev_fips_parse_3des.c                    |  259 +++++
 .../cryptodev_fips_parse_aes.c                     |  188 +++
 .../cryptodev_fips_parse_ccm.c                     |  272 +++++
 .../cryptodev_fips_parse_cmac.c                    |  116 ++
 .../cryptodev_fips_parse_gcm.c                     |  125 ++
 .../cryptodev_fips_parse_hmac.c                    |  105 ++
 .../cryptodev_fips_parse_validate.c                |  593 ++++++++++
 .../cryptodev_fips_validate.h                      |  234 ++++
 examples/cryptodev_fips_validate/main.c            | 1221 ++++++++++++++++++++
 examples/cryptodev_fips_validate/meson.build       |   20 +
 14 files changed, 3320 insertions(+)
 create mode 100644 doc/guides/sample_app_ug/fips_validation.rst
 create mode 100644 examples/cryptodev_fips_validate/Makefile
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_ccm.c
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_cmac.c
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_gcm.c
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_hmac.c
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_validate.h
 create mode 100644 examples/cryptodev_fips_validate/main.c
 create mode 100644 examples/cryptodev_fips_validate/meson.build

-- 
2.9.5

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

* [dpdk-dev] [PATCH v4 1/8] examples: add fips validation into examples
  2018-10-12 14:44 [dpdk-dev] [PATCH v4 0/8] FIPS validation capability Marko Kovacevic
@ 2018-10-12 14:44 ` Marko Kovacevic
  2018-10-12 14:44 ` [dpdk-dev] [PATCH v4 2/8] examples: add aes parser and enablement for test types Marko Kovacevic
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-12 14:44 UTC (permalink / raw)
  To: dev; +Cc: roy.fan.zhang, akhil.goyal, arkadiuszx.kusztal, Marko Kovacevic

Added FIPS application into the examples to allow
users to use a simple sample app to validate
their systems and be able to get FIPS certification.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
---
 examples/cryptodev_fips_validate/Makefile          |  69 +++
 .../cryptodev_fips_parse_validate.c                | 562 +++++++++++++++++++++
 .../cryptodev_fips_validate.h                      | 150 ++++++
 examples/cryptodev_fips_validate/main.c            | 388 ++++++++++++++
 examples/cryptodev_fips_validate/meson.build       |  14 +
 5 files changed, 1183 insertions(+)
 create mode 100644 examples/cryptodev_fips_validate/Makefile
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_validate.h
 create mode 100644 examples/cryptodev_fips_validate/main.c
 create mode 100644 examples/cryptodev_fips_validate/meson.build

diff --git a/examples/cryptodev_fips_validate/Makefile b/examples/cryptodev_fips_validate/Makefile
new file mode 100644
index 0000000..5515aa6
--- /dev/null
+++ b/examples/cryptodev_fips_validate/Makefile
@@ -0,0 +1,69 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2010-2014 Intel Corporation
+
+# binary name
+APP = cryptodev_fips_validate_app
+
+# all source are stored in SRCS-y
+SRCS-y += cryptodev_fips_parse_validate.c
+SRCS-y += main.c
+
+# Build using pkg-config variables if possible
+$(shell pkg-config --exists libdpdk)
+ifeq ($(.SHELLSTATUS),0)
+
+all: shared
+.PHONY: shared static
+shared: build/$(APP)-shared
+	ln -sf $(APP)-shared build/$(APP)
+static: build/$(APP)-static
+	ln -sf $(APP)-static build/$(APP)
+
+PC_FILE := $(shell pkg-config --path libdpdk)
+CFLAGS += -O3 $(shell pkg-config --cflags libdpdk)
+LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk)
+LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk)
+
+build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
+	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
+
+build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build
+	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC)
+
+build:
+	@mkdir -p $@
+
+.PHONY: clean
+clean:
+	rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared
+	rmdir --ignore-fail-on-non-empty build
+
+else
+
+ifeq ($(RTE_SDK),)
+$(error "Please define RTE_SDK environment variable")
+endif
+
+# Default target, can be overridden by command line or environment
+RTE_TARGET ?= x86_64-native-linuxapp-gcc
+
+INC += $(sort $(wildcard *.h))
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+CFLAGS += $(WERROR_FLAGS)
+
+# workaround for a gcc bug with noreturn attribute
+# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603
+ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
+CFLAGS_main.o += -Wno-return-type
+endif
+
+CFLAGS += -DALLOW_EXPERIMENTAL_API
+CFLAGS += -I$(SRCDIR)
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+include $(RTE_SDK)/mk/rte.extapp.mk
+
+endif
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
new file mode 100644
index 0000000..aec5bb9
--- /dev/null
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
@@ -0,0 +1,562 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <rte_string_fns.h>
+#include <rte_cryptodev.h>
+#include <rte_malloc.h>
+
+#include "cryptodev_fips_validate.h"
+
+#define skip_white_spaces(pos)			\
+({						\
+	__typeof__(pos) _p = (pos);		\
+	for ( ; isspace(*_p); _p++)		\
+		;				\
+	_p;					\
+})
+
+static int
+get_file_line(void)
+{
+	FILE *fp = info.fp_rd;
+	char *line = info.one_line_text;
+	char c;
+	uint32_t loc = 0;
+
+	memset(line, 0, MAX_LINE_CHAR);
+	while ((c = fgetc(fp)) != EOF) {
+		if (loc >= MAX_LINE_CHAR - 1)
+			return -ENOMEM;
+		if (c == '\n')
+			return 0;
+		line[loc++] = c;
+	}
+
+	if (c == EOF)
+		return -EOF;
+
+	return 0;
+}
+
+int
+fips_test_fetch_one_block(void)
+{
+	size_t size;
+	int ret = 0;
+	uint32_t i;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		free(info.vec[i]);
+		info.vec[i] = NULL;
+	}
+
+	i = 0;
+	do {
+		if (i >= MAX_LINE_PER_VECTOR) {
+			ret = -ENOMEM;
+			goto error_exit;
+		}
+
+		ret = get_file_line();
+		size = strlen(info.one_line_text);
+		if (size == 0)
+			break;
+
+		info.vec[i] = calloc(1, size + 5);
+		if (info.vec[i] == NULL)
+			goto error_exit;
+
+		strlcpy(info.vec[i], info.one_line_text, size + 1);
+		i++;
+	} while (ret == 0);
+
+	info.nb_vec_lines = i;
+
+	return ret;
+
+error_exit:
+	for (i = 0; i < MAX_LINE_PER_VECTOR; i++)
+		if (info.vec[i] != NULL) {
+			free(info.vec[i]);
+			info.vec[i] = NULL;
+		}
+
+	info.nb_vec_lines = 0;
+
+	return -ENOMEM;
+}
+
+static int
+fips_test_parse_header(void)
+{
+	uint32_t i;
+	char *tmp;
+	int ret;
+	time_t t = time(NULL);
+	struct tm *tm_now = localtime(&t);
+
+	ret = fips_test_fetch_one_block();
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+
+		tmp = strstr(info.vec[i], "# Config info for ");
+		if (tmp != NULL) {
+			fprintf(info.fp_wr, "%s%s\n", "# Config info for DPDK Cryptodev ",
+					info.device_name);
+			continue;
+		}
+
+		tmp = strstr(info.vec[i], "#  HMAC information for ");
+		if (tmp != NULL) {
+			fprintf(info.fp_wr, "%s%s\n", "#  HMAC information for "
+				"DPDK Cryptodev ",
+				info.device_name);
+			continue;
+		}
+
+		tmp = strstr(info.vec[i], "# Config Info for : ");
+		if (tmp != NULL) {
+
+			fprintf(info.fp_wr, "%s%s\n", "# Config Info for DPDK Cryptodev : ",
+					info.device_name);
+			continue;
+		}
+
+		tmp = strstr(info.vec[i], "# information for ");
+		if (tmp != NULL) {
+
+			char tmp_output[128] = {0};
+
+			strlcpy(tmp_output, info.vec[i], tmp - info.vec[i] + 1);
+
+			fprintf(info.fp_wr, "%s%s%s\n", tmp_output,
+					"information for DPDK Cryptodev ",
+					info.device_name);
+			continue;
+		}
+
+		tmp = strstr(info.vec[i], " test information for ");
+		if (tmp != NULL) {
+			char tmp_output[128] = {0};
+
+			strlcpy(tmp_output, info.vec[i], tmp - info.vec[i] + 1);
+
+			fprintf(info.fp_wr, "%s%s%s\n", tmp_output,
+					"test information for DPDK Cryptodev ",
+					info.device_name);
+			continue;
+		}
+
+		if (i == info.nb_vec_lines - 1) {
+			/** update the time as current time, write to file */
+			fprintf(info.fp_wr, "%s%s\n", "# Generated on ",
+					asctime(tm_now));
+			continue;
+		}
+
+		/* to this point, no field need to update,
+		 *  only copy to rsp file
+		 */
+		fprintf(info.fp_wr, "%s\n", info.vec[i]);
+	}
+
+	return 0;
+}
+
+static int
+parse_file_type(const char *path)
+{
+	const char *tmp = path + strlen(path) - 3;
+
+	if (strstr(tmp, REQ_FILE_PERFIX))
+		info.file_type = FIPS_TYPE_REQ;
+	else if (strstr(tmp, RSP_FILE_PERFIX))
+		info.file_type = FIPS_TYPE_RSP;
+	else if (strstr(path, FAX_FILE_PERFIX))
+		info.file_type = FIPS_TYPE_FAX;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+int
+fips_test_init(const char *req_file_path, const char *rsp_file_path,
+		const char *device_name)
+{
+	if (strcmp(req_file_path, rsp_file_path) == 0) {
+		RTE_LOG(ERR, USER1, "File paths cannot be the same\n");
+		return -EINVAL;
+	}
+
+	fips_test_clear();
+
+	info.algo = FIPS_TEST_ALGO_MAX;
+	if (parse_file_type(req_file_path) < 0) {
+		RTE_LOG(ERR, USER1, "File %s type not supported\n",
+				req_file_path);
+		return -EINVAL;
+	}
+
+	info.fp_rd = fopen(req_file_path, "r");
+	if (!info.fp_rd) {
+		RTE_LOG(ERR, USER1, "Cannot open file %s\n", req_file_path);
+		return -EINVAL;
+	}
+
+	info.fp_wr = fopen(rsp_file_path, "w");
+	if (!info.fp_wr) {
+		RTE_LOG(ERR, USER1, "Cannot open file %s\n", rsp_file_path);
+		return -EINVAL;
+	}
+
+	info.one_line_text = calloc(1, MAX_LINE_CHAR);
+	if (!info.one_line_text) {
+		RTE_LOG(ERR, USER1, "Insufficient memory\n");
+		return -ENOMEM;
+	}
+
+	strlcpy(info.device_name, device_name, sizeof(info.device_name));
+
+	if (fips_test_parse_header() < 0) {
+		RTE_LOG(ERR, USER1, "Failed parsing header\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+void
+fips_test_clear(void)
+{
+	if (info.fp_rd)
+		fclose(info.fp_rd);
+	if (info.fp_wr)
+		fclose(info.fp_wr);
+	if (info.one_line_text)
+		free(info.one_line_text);
+	if (info.nb_vec_lines) {
+		uint32_t i;
+
+		for (i = 0; i < info.nb_vec_lines; i++)
+			free(info.vec[i]);
+	}
+
+	memset(&info, 0, sizeof(info));
+}
+
+int
+fips_test_parse_one_case(void)
+{
+	uint32_t i, j = 0;
+	uint32_t is_interim = 0;
+	int ret;
+
+	if (info.interim_callbacks) {
+		for (i = 0; i < info.nb_vec_lines; i++) {
+			for (j = 0; info.interim_callbacks[j].key != NULL; j++)
+				if (strstr(info.vec[i],
+					info.interim_callbacks[j].key)) {
+					is_interim = 1;
+
+					ret = info.interim_callbacks[j].cb(
+						info.interim_callbacks[j].key,
+						info.vec[i],
+						info.interim_callbacks[j].val);
+					if (ret < 0)
+						return ret;
+				}
+		}
+	}
+
+	if (is_interim) {
+		for (i = 0; i < info.nb_vec_lines; i++)
+			fprintf(info.fp_wr, "%s\n", info.vec[i]);
+		fprintf(info.fp_wr, "\n");
+		return 1;
+	}
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		for (j = 0; info.callbacks[j].key != NULL; j++)
+			if (strstr(info.vec[i], info.callbacks[j].key)) {
+				ret = info.callbacks[j].cb(
+					info.callbacks[j].key,
+					info.vec[i], info.callbacks[j].val);
+				if (ret < 0)
+					return ret;
+				break;
+			}
+	}
+
+	return 0;
+}
+
+void
+fips_test_write_one_case(void)
+{
+	uint32_t i;
+
+	for (i = 0; i < info.nb_vec_lines; i++)
+		fprintf(info.fp_wr, "%s\n", info.vec[i]);
+}
+
+static int
+parser_read_uint64_hex(uint64_t *value, const char *p)
+{
+	char *next;
+	uint64_t val;
+
+	p = skip_white_spaces(p);
+
+	val = strtoul(p, &next, 16);
+	if (p == next)
+		return -EINVAL;
+
+	p = skip_white_spaces(next);
+	if (*p != '\0')
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
+int
+parser_read_uint8_hex(uint8_t *value, const char *p)
+{
+	uint64_t val = 0;
+	int ret = parser_read_uint64_hex(&val, p);
+
+	if (ret < 0)
+		return ret;
+
+	if (val > UINT8_MAX)
+		return -ERANGE;
+
+	*value = val;
+	return 0;
+}
+
+int
+parse_uint8_known_len_hex_str(const char *key, char *src, struct fips_val *val)
+{
+	struct fips_val tmp_val = {0};
+	uint32_t len = val->len;
+	int ret;
+
+	if (len == 0) {
+		if (val->val != NULL) {
+			rte_free(val->val);
+			val->val = NULL;
+		}
+
+		return 0;
+	}
+
+	ret = parse_uint8_hex_str(key, src, &tmp_val);
+	if (ret < 0)
+		return ret;
+
+	if (tmp_val.len == val->len) {
+		val->val = tmp_val.val;
+		return 0;
+	}
+
+	if (tmp_val.len < val->len) {
+		rte_free(tmp_val.val);
+		return -EINVAL;
+	}
+
+	val->val = rte_zmalloc(NULL, val->len, 0);
+	if (!val->val) {
+		rte_free(tmp_val.val);
+		memset(val, 0, sizeof(*val));
+		return -ENOMEM;
+	}
+
+	memcpy(val->val, tmp_val.val, val->len);
+	rte_free(tmp_val.val);
+
+	return 0;
+}
+
+int
+parse_uint8_hex_str(const char *key, char *src, struct fips_val *val)
+{
+	uint32_t len, j;
+
+	src += strlen(key);
+
+	len = strlen(src) / 2;
+
+	if (val->val) {
+		rte_free(val->val);
+		val->val = NULL;
+	}
+
+	val->val = rte_zmalloc(NULL, len, 0);
+	if (!val->val)
+		return -1;
+
+	for (j = 0; j < len; j++) {
+		char byte[3] = {src[j * 2], src[j * 2 + 1], '\0'};
+
+		if (parser_read_uint8_hex(&val->val[j], byte) < 0) {
+			rte_free(val->val);
+			memset(val, 0, sizeof(*val));
+			return -EINVAL;
+		}
+	}
+
+	val->len = len;
+
+	return 0;
+}
+
+int
+parser_read_uint32_val(const char *key, char *src, struct fips_val *val)
+{
+	char *data = src + strlen(key);
+	size_t data_len = strlen(data);
+	int ret;
+
+	if (data[data_len - 1] == ']') {
+		char *tmp_data = calloc(1, data_len + 1);
+
+		if (tmp_data == NULL)
+			return -ENOMEM;
+
+		strlcpy(tmp_data, data, data_len);
+
+		ret = parser_read_uint32(&val->len, tmp_data);
+
+		free(tmp_data);
+	} else
+		ret = parser_read_uint32(&val->len, data);
+
+	return ret;
+}
+
+int
+parser_read_uint32_bit_val(const char *key, char *src, struct fips_val *val)
+{
+	int ret;
+
+	ret = parser_read_uint32_val(key, src, val);
+
+	if (ret < 0)
+		return ret;
+
+	val->len /= 8;
+
+	return 0;
+}
+
+int
+writeback_hex_str(const char *key, char *dst, struct fips_val *val)
+{
+	char *str = dst;
+	uint32_t len;
+
+	str += strlen(key);
+
+	for (len = 0; len < val->len; len++)
+		snprintf(str + len * 2, 255, "%02x", val->val[len]);
+
+	return 0;
+}
+
+static int
+parser_read_uint64(uint64_t *value, const char *p)
+{
+	char *next;
+	uint64_t val;
+
+	p = skip_white_spaces(p);
+	if (!isdigit(*p))
+		return -EINVAL;
+
+	val = strtoul(p, &next, 10);
+	if (p == next)
+		return -EINVAL;
+
+	p = next;
+	switch (*p) {
+	case 'T':
+		val *= 1024ULL;
+		/* fall through */
+	case 'G':
+		val *= 1024ULL;
+		/* fall through */
+	case 'M':
+		val *= 1024ULL;
+		/* fall through */
+	case 'k':
+	case 'K':
+		val *= 1024ULL;
+		p++;
+		break;
+	}
+
+	p = skip_white_spaces(p);
+	if (*p != '\0')
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
+int
+parser_read_uint32(uint32_t *value, char *p)
+{
+	uint64_t val = 0;
+	int ret = parser_read_uint64(&val, p);
+
+	if (ret < 0)
+		return ret;
+
+	if (val > UINT32_MAX)
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
+void
+parse_write_hex_str(struct fips_val *src)
+{
+	writeback_hex_str("", info.one_line_text, src);
+
+	fprintf(info.fp_wr, "%s\n", info.one_line_text);
+}
+
+int
+update_info_vec(uint32_t count)
+{
+	const struct fips_test_callback *cb;
+	uint32_t i, j;
+
+	if (!info.writeback_callbacks)
+		return -1;
+
+	cb = &info.writeback_callbacks[0];
+
+	snprintf(info.vec[0], strlen(info.vec[0]) + 4, "%s%u", cb->key, count);
+
+	for (i = 1; i < info.nb_vec_lines; i++) {
+		for (j = 1; info.writeback_callbacks[j].key != NULL; j++) {
+			cb = &info.writeback_callbacks[j];
+			if (strstr(info.vec[i], cb->key)) {
+				cb->cb(cb->key, info.vec[i], cb->val);
+				break;
+			}
+		}
+	}
+
+	return 0;
+}
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
new file mode 100644
index 0000000..beb6bed
--- /dev/null
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
@@ -0,0 +1,150 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _CRYPTODEV_NIST_FIPS_PARSER_H_
+#define _CRYPTODEV_NIST_FIPS_PARSER_H_
+
+#define FIPS_PARSE_ERR(fmt, args)					\
+	RTE_LOG(ERR, USER1, "FIPS parse error" ## fmt ## "\n", ## args)
+
+#define ERR_MSG_SIZE		128
+#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 MAX_STRING_SIZE		64
+
+#define POSITIVE_TEST		0
+#define NEGATIVE_TEST		-1
+
+#define REQ_FILE_PERFIX		"req"
+#define RSP_FILE_PERFIX		"rsp"
+#define FAX_FILE_PERFIX		"fax"
+
+enum fips_test_algorithms {
+		FIPS_TEST_ALGO_MAX
+};
+
+enum file_types {
+	FIPS_TYPE_REQ = 1,
+	FIPS_TYPE_FAX,
+	FIPS_TYPE_RSP
+};
+
+enum fips_test_op {
+	FIPS_TEST_ENC_AUTH_GEN = 1,
+	FIPS_TEST_DEC_AUTH_VERIF,
+};
+
+#define MAX_LINE_PER_VECTOR            16
+
+struct fips_val {
+	uint8_t *val;
+	uint32_t len;
+};
+
+struct fips_test_vector {
+	union {
+		struct {
+			struct fips_val key;
+			struct fips_val digest;
+			struct fips_val auth_aad;
+			struct fips_val aad;
+		} cipher_auth;
+		struct {
+			struct fips_val key;
+			struct fips_val digest;
+			struct fips_val aad;
+		} aead;
+	};
+
+	struct fips_val pt;
+	struct fips_val ct;
+	struct fips_val iv;
+
+	enum rte_crypto_op_status status;
+};
+
+typedef int (*post_prcess_t)(struct fips_val *val);
+
+typedef int (*parse_callback_t)(const char *key, char *text,
+		struct fips_val *val);
+
+struct fips_test_callback {
+	const char *key;
+	parse_callback_t cb;
+	struct fips_val *val;
+};
+
+struct fips_test_interim_info {
+	FILE *fp_rd;
+	FILE *fp_wr;
+	enum file_types file_type;
+	enum fips_test_algorithms algo;
+	char *one_line_text;
+	char *vec[MAX_LINE_PER_VECTOR];
+	uint32_t nb_vec_lines;
+	//uint8_t cryptodev_id;
+	char device_name[MAX_STRING_SIZE];
+
+	enum fips_test_op op;
+
+	const struct fips_test_callback *callbacks;
+	const struct fips_test_callback *interim_callbacks;
+	const struct fips_test_callback *writeback_callbacks;
+
+	post_prcess_t parse_writeback;
+	post_prcess_t kat_check;
+};
+
+extern struct fips_test_vector vec;
+extern struct fips_test_interim_info info;
+
+int
+fips_test_init(const char *req_file_path, const char *rsp_file_path,
+		const char *device_name);
+
+void
+fips_test_clear(void);
+
+int
+fips_test_fetch_one_block(void);
+
+int
+fips_test_parse_one_case(void);
+
+void
+fips_test_write_one_case(void);
+
+int
+parser_read_uint8_hex(uint8_t *value, const char *p);
+
+int
+parse_uint8_hex_str(const char *key, char *src, struct fips_val *val);
+
+int
+parse_uint8_known_len_hex_str(const char *key, char *src, struct fips_val *val);
+
+int
+parser_read_uint32_val(const char *key, char *src, struct fips_val *val);
+
+int
+parser_read_uint32_bit_val(const char *key, char *src, struct fips_val *val);
+
+int
+parser_read_uint32(uint32_t *value, char *p);
+
+int
+parser_read_uint32_val(const char *key, char *src, struct fips_val *val);
+
+int
+writeback_hex_str(const char *key, char *dst, struct fips_val *val);
+
+void
+parse_write_hex_str(struct fips_val *src);
+
+int
+update_info_vec(uint32_t count);
+
+#endif
diff --git a/examples/cryptodev_fips_validate/main.c b/examples/cryptodev_fips_validate/main.c
new file mode 100644
index 0000000..4f14b04
--- /dev/null
+++ b/examples/cryptodev_fips_validate/main.c
@@ -0,0 +1,388 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <sys/stat.h>
+#include <getopt.h>
+#include <dirent.h>
+
+#include <rte_cryptodev.h>
+#include <rte_cryptodev_pmd.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_string_fns.h>
+
+#include "cryptodev_fips_validate.h"
+
+#define REQ_FILE_PATH_KEYWORD	"req-file"
+#define RSP_FILE_PATH_KEYWORD	"rsp-file"
+#define FOLDER_KEYWORD		"path-is-folder"
+#define CRYPTODEV_KEYWORD	"cryptodev"
+#define CRYPTODEV_ID_KEYWORD	"cryptodev-id"
+
+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;
+	uint32_t dev_id;
+	struct rte_mempool *mpool;
+	struct rte_mempool *op_pool;
+	struct rte_mbuf *mbuf;
+	struct rte_crypto_op *op;
+	struct rte_cryptodev_sym_session *sess;
+} env;
+
+static int
+cryptodev_fips_validate_app_int(void)
+{
+	struct rte_cryptodev_config conf = {rte_socket_id(), 1};
+	struct rte_cryptodev_qp_conf qp_conf = {128};
+	int ret;
+
+	ret = rte_cryptodev_configure(env.dev_id, &conf);
+	if (ret < 0)
+		return ret;
+
+	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", 128, 0, 0,
+			UINT16_MAX, rte_socket_id());
+	if (!env.mpool)
+		return ret;
+
+	ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
+			rte_socket_id(), env.mpool);
+	if (ret < 0)
+		return ret;
+
+	ret = -ENOMEM;
+
+	env.op_pool = rte_crypto_op_pool_create(
+			"FIPS_OP_POOL",
+			RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+			1, 0,
+			16,
+			rte_socket_id());
+	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;
+
+	return 0;
+
+error_exit:
+	rte_mempool_free(env.mpool);
+	if (env.op_pool)
+		rte_mempool_free(env.op_pool);
+
+	return ret;
+}
+
+static void
+cryptodev_fips_validate_app_uninit(void)
+{
+	rte_pktmbuf_free(env.mbuf);
+	rte_crypto_op_free(env.op);
+	rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
+	rte_cryptodev_sym_session_free(env.sess);
+	rte_mempool_free(env.mpool);
+	rte_mempool_free(env.op_pool);
+}
+
+static int
+fips_test_one_file(void);
+
+static int
+parse_cryptodev_arg(char *arg)
+{
+	int id = rte_cryptodev_get_dev_id(arg);
+
+	if (id < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev name %s\n",
+				id, arg);
+		return id;
+	}
+
+	env.dev_id = (uint32_t)id;
+
+	return 0;
+}
+
+static int
+parse_cryptodev_id_arg(char *arg)
+{
+	uint32_t cryptodev_id;
+
+	if (parser_read_uint32(&cryptodev_id, arg) < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n",
+				-EINVAL, arg);
+		return -1;
+	}
+
+
+	if (!rte_cryptodev_pmd_is_valid_dev(cryptodev_id)) {
+		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n",
+				cryptodev_id, arg);
+		return -1;
+	}
+
+	env.dev_id = (uint32_t)cryptodev_id;
+
+	return 0;
+}
+
+static void
+cryptodev_fips_validate_usage(const char *prgname)
+{
+	printf("%s [EAL options] --\n"
+		"  --%s: REQUEST-FILE-PATH\n"
+		"  --%s: RESPONSE-FILE-PATH\n"
+		"  --%s: indicating both paths are folders\n"
+		"  --%s: CRYPTODEV-NAME\n"
+		"  --%s: CRYPTODEV-ID-NAME\n",
+		prgname, REQ_FILE_PATH_KEYWORD, RSP_FILE_PATH_KEYWORD,
+		FOLDER_KEYWORD, CRYPTODEV_KEYWORD, CRYPTODEV_ID_KEYWORD);
+}
+
+static int
+cryptodev_fips_validate_parse_args(int argc, char **argv)
+{
+	int opt, ret;
+	char *prgname = argv[0];
+	char **argvopt;
+	int option_index;
+	struct option lgopts[] = {
+			{REQ_FILE_PATH_KEYWORD, required_argument, 0, 0},
+			{RSP_FILE_PATH_KEYWORD, required_argument, 0, 0},
+			{FOLDER_KEYWORD, no_argument, 0, 0},
+			{CRYPTODEV_KEYWORD, required_argument, 0, 0},
+			{CRYPTODEV_ID_KEYWORD, required_argument, 0, 0},
+			{NULL, 0, 0, 0}
+	};
+
+	argvopt = argv;
+
+	while ((opt = getopt_long(argc, argvopt, "s:",
+				  lgopts, &option_index)) != EOF) {
+
+		switch (opt) {
+		case 0:
+			if (strcmp(lgopts[option_index].name,
+					REQ_FILE_PATH_KEYWORD) == 0)
+				env.req_path = optarg;
+			else if (strcmp(lgopts[option_index].name,
+					RSP_FILE_PATH_KEYWORD) == 0)
+				env.rsp_path = optarg;
+			else if (strcmp(lgopts[option_index].name,
+					FOLDER_KEYWORD) == 0)
+				env.is_path_folder = 1;
+			else if (strcmp(lgopts[option_index].name,
+					CRYPTODEV_KEYWORD) == 0) {
+				ret = parse_cryptodev_arg(optarg);
+				if (ret < 0) {
+					cryptodev_fips_validate_usage(prgname);
+					return -EINVAL;
+				}
+			} else if (strcmp(lgopts[option_index].name,
+					CRYPTODEV_ID_KEYWORD) == 0) {
+				ret = parse_cryptodev_id_arg(optarg);
+				if (ret < 0) {
+					cryptodev_fips_validate_usage(prgname);
+					return -EINVAL;
+				}
+			} else {
+				cryptodev_fips_validate_usage(prgname);
+				return -EINVAL;
+			}
+			break;
+		default:
+			return -1;
+		}
+	}
+
+	if (env.req_path == NULL || env.rsp_path == NULL ||
+			env.dev_id == UINT32_MAX) {
+		cryptodev_fips_validate_usage(prgname);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+	int ret;
+
+	ret = rte_eal_init(argc, argv);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
+		return -1;
+	}
+
+	argc -= ret;
+	argv += ret;
+
+	ret = cryptodev_fips_validate_parse_args(argc, argv);
+	if (ret < 0)
+		rte_exit(EXIT_FAILURE, "Failed to parse arguments!\n");
+
+	ret = cryptodev_fips_validate_app_int();
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
+		return -1;
+	}
+
+	if (!env.is_path_folder) {
+		printf("Processing file %s... ", env.req_path);
+
+		ret = fips_test_init(env.req_path, env.rsp_path,
+			rte_cryptodev_name_get(env.dev_id));
+		if (ret < 0) {
+			RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
+					ret, env.req_path);
+			goto exit;
+		}
+
+
+		ret = fips_test_one_file();
+		if (ret < 0) {
+			RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
+					ret, env.req_path);
+			goto exit;
+		}
+
+		printf("Done\n");
+
+	} else {
+		struct dirent *dir;
+		DIR *d_req, *d_rsp;
+		char req_path[1024];
+		char rsp_path[1024];
+
+		d_req = opendir(env.req_path);
+		if (!d_req) {
+			RTE_LOG(ERR, USER1, "Error %i: Path %s not exist\n",
+					-EINVAL, env.req_path);
+			goto exit;
+		}
+
+		d_rsp = opendir(env.rsp_path);
+		if (!d_rsp) {
+			ret = mkdir(env.rsp_path, 0700);
+			if (ret == 0)
+				d_rsp = opendir(env.rsp_path);
+			else {
+				RTE_LOG(ERR, USER1, "Error %i: Invalid %s\n",
+						-EINVAL, env.rsp_path);
+				goto exit;
+			}
+		}
+		closedir(d_rsp);
+
+		while ((dir = readdir(d_req)) != NULL) {
+			if (strstr(dir->d_name, "req") == NULL)
+				continue;
+
+			snprintf(req_path, 1023, "%s/%s", env.req_path,
+					dir->d_name);
+			snprintf(rsp_path, 1023, "%s/%s", env.rsp_path,
+					dir->d_name);
+			strlcpy(strstr(rsp_path, "req"), "rsp", 4);
+
+			printf("Processing file %s... ", req_path);
+
+			ret = fips_test_init(req_path, rsp_path,
+			rte_cryptodev_name_get(env.dev_id));
+			if (ret < 0) {
+				RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
+						ret, req_path);
+				break;
+			}
+
+			ret = fips_test_one_file();
+			if (ret < 0) {
+				RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
+						ret, req_path);
+				break;
+			}
+
+			printf("Done\n");
+		}
+
+		closedir(d_req);
+	}
+
+
+exit:
+	fips_test_clear();
+	cryptodev_fips_validate_app_uninit();
+
+	return ret;
+
+}
+
+static void
+print_test_block(void)
+{
+	uint32_t i;
+
+	for (i = 0; i < info.nb_vec_lines; i++)
+		printf("%s\n", info.vec[i]);
+
+	printf("\n");
+}
+
+static int
+fips_test_one_file(void)
+{
+	int fetch_ret = 0, ret;
+
+	while (fetch_ret == 0) {
+		fetch_ret = fips_test_fetch_one_block();
+		if (fetch_ret < 0) {
+			RTE_LOG(ERR, USER1, "Error %i: Fetch block\n",
+					fetch_ret);
+			ret = fetch_ret;
+			goto error_one_case;
+		}
+
+		if (info.nb_vec_lines == 0) {
+			if (fetch_ret == -EOF)
+				break;
+
+			fprintf(info.fp_wr, "\n");
+			continue;
+		}
+
+		ret = fips_test_parse_one_case();
+		switch (ret) {
+		case 0:
+			if (ret == 0)
+				break;
+			RTE_LOG(ERR, USER1, "Error %i: test block\n",
+					ret);
+			goto error_one_case;
+		case 1:
+			break;
+		default:
+			RTE_LOG(ERR, USER1, "Error %i: Parse block\n",
+					ret);
+			goto error_one_case;
+		}
+
+		continue;
+error_one_case:
+		print_test_block();
+	}
+
+	fips_test_clear();
+
+}
diff --git a/examples/cryptodev_fips_validate/meson.build b/examples/cryptodev_fips_validate/meson.build
new file mode 100644
index 0000000..e417733
--- /dev/null
+++ b/examples/cryptodev_fips_validate/meson.build
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Intel Corporation
+
+# meson file, for building this example as part of a main DPDK build.
+#
+# To build this example as a standalone application with an already-installed
+# DPDK instance, use 'make'
+
+deps += ['cryptodev', 'bus_pci']
+allow_experimental_apis = true
+sources = files(
+	'cryptodev_fips_parse_validate.c',
+	'main.c'
+)
-- 
2.9.5

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

* [dpdk-dev] [PATCH v4 2/8] examples: add aes parser and enablement for test types
  2018-10-12 14:44 [dpdk-dev] [PATCH v4 0/8] FIPS validation capability Marko Kovacevic
  2018-10-12 14:44 ` [dpdk-dev] [PATCH v4 1/8] examples: add fips validation into examples Marko Kovacevic
@ 2018-10-12 14:44 ` Marko Kovacevic
  2018-10-12 14:44 ` [dpdk-dev] [PATCH v4 3/8] examples: add hmac parser Marko Kovacevic
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-12 14:44 UTC (permalink / raw)
  To: dev; +Cc: roy.fan.zhang, akhil.goyal, arkadiuszx.kusztal, Marko Kovacevic

Added enablement for AES-CBC parser, to allow the
application to parser the aes request file and to validate all
test types supported.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
---
 examples/cryptodev_fips_validate/Makefile          |   1 +
 .../cryptodev_fips_parse_aes.c                     | 186 +++++++++++
 .../cryptodev_fips_parse_validate.c                |   6 +
 .../cryptodev_fips_validate.h                      |  24 ++
 examples/cryptodev_fips_validate/main.c            | 346 ++++++++++++++++++++-
 examples/cryptodev_fips_validate/meson.build       |   1 +
 6 files changed, 563 insertions(+), 1 deletion(-)
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c

diff --git a/examples/cryptodev_fips_validate/Makefile b/examples/cryptodev_fips_validate/Makefile
index 5515aa6..f058081 100644
--- a/examples/cryptodev_fips_validate/Makefile
+++ b/examples/cryptodev_fips_validate/Makefile
@@ -5,6 +5,7 @@
 APP = cryptodev_fips_validate_app
 
 # all source are stored in SRCS-y
+SRCS-y := cryptodev_fips_parse_aes.c
 SRCS-y += cryptodev_fips_parse_validate.c
 SRCS-y += main.c
 
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c
new file mode 100644
index 0000000..39dbd6f
--- /dev/null
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c
@@ -0,0 +1,186 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+
+#include <rte_cryptodev.h>
+
+#include "cryptodev_fips_validate.h"
+
+#define MODE_STR	"AESVS"
+#define ALGO_STR	"test data for "
+#define OP_STR		"State"
+#define KEY_SIZE_STR	"Key Length : "
+
+
+#define COUNT_STR	"COUNT = "
+#define KEY_STR		"KEY = "
+#define IV_STR		"IV = "
+#define PT_STR		"PLAINTEXT = "
+#define CT_STR		"CIPHERTEXT = "
+
+#define OP_ENC_STR	"ENCRYPT"
+#define OP_DEC_STR	"DECRYPT"
+
+struct {
+	uint32_t type;
+	const char *desc;
+} aes_test_types[] = {
+		{AESAVS_TYPE_GFXBOX, "GFSbox"},
+		{AESAVS_TYPE_KEYSBOX, "KeySbox"},
+		{AESAVS_TYPE_VARKEY, "VarKey"},
+		{AESAVS_TYPE_VARTXT, "VarTxt"},
+		{AESAVS_TYPE_MMT, "MMT"},
+		{AESAVS_TYPE_MCT, "MCT"},
+};
+
+struct aes_test_algo {
+	const char *name;
+	enum rte_crypto_cipher_algorithm algo;
+} const algo_con[] = {
+		{"CBC", RTE_CRYPTO_CIPHER_AES_CBC},
+};
+
+static int
+parse_interim_enc_dec(const char *key,
+		__attribute__((__unused__)) char *text,
+		__attribute__((__unused__)) struct fips_val *val)
+{
+	if (strcmp(key, OP_ENC_STR) == 0)
+		info.op = FIPS_TEST_ENC_AUTH_GEN;
+	else if (strcmp(key, OP_DEC_STR) == 0)
+		info.op = FIPS_TEST_DEC_AUTH_VERIF;
+	else
+		return -1;
+
+	return 0;
+}
+
+struct fips_test_callback aes_tests_interim[] = {
+		{OP_ENC_STR, parse_interim_enc_dec, NULL},
+		{OP_DEC_STR, parse_interim_enc_dec, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback aes_tests_vectors[] = {
+		{KEY_STR, parse_uint8_hex_str, &vec.cipher_auth.key},
+		{IV_STR, parse_uint8_hex_str, &vec.iv},
+		{PT_STR, parse_uint8_hex_str, &vec.pt},
+		{CT_STR, parse_uint8_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback aes_tests_interim_vectors[] = {
+		{OP_ENC_STR, parse_interim_enc_dec, NULL},
+		{OP_DEC_STR, parse_interim_enc_dec, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback aes_writeback_callbacks[] = {
+		/** First element is used to pass COUNT string */
+		{COUNT_STR, NULL, NULL},
+		{IV_STR, writeback_hex_str, &vec.iv},
+		{KEY_STR, writeback_hex_str, &vec.cipher_auth.key},
+		{PT_STR, writeback_hex_str, &vec.pt},
+		{CT_STR, writeback_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+static int
+parse_test_aes_writeback(struct fips_val *val)
+{
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN)
+		fprintf(info.fp_wr, "%s", CT_STR);
+	else
+		fprintf(info.fp_wr, "%s", PT_STR);
+
+	parse_write_hex_str(val);
+
+	return 0;
+}
+
+static int
+rsp_test_aes_check(struct fips_val *val)
+{
+	struct fips_val *data;
+
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN)
+		data = &vec.ct;
+	else
+		data = &vec.pt;
+
+	if (memcmp(val->val, data->val, val->len) == 0)
+		fprintf(info.fp_wr, "Success\n");
+	else
+		fprintf(info.fp_wr, "Failed\n");
+
+	return 0;
+}
+
+int
+parse_test_aes_init(void)
+{
+	char *tmp;
+	uint32_t i, j;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		char *line = info.vec[i];
+
+		tmp = strstr(line, MODE_STR);
+		if (tmp) {
+			for (j = 0; j < RTE_DIM(aes_test_types); j++)
+				if (strstr(line, aes_test_types[j].desc)) {
+					info.interim_info.aes_data.test_type =
+							aes_test_types[j].type;
+					break;
+				}
+
+			if (j >= RTE_DIM(aes_test_types))
+				return -EINVAL;
+
+			tmp = strstr(line, ALGO_STR);
+			if (!tmp)
+				return -EINVAL;
+
+			tmp += strlen(ALGO_STR);
+			for (j = 0; j < RTE_DIM(algo_con); j++)
+				if (strcmp(algo_con[j].name, tmp) == 0) {
+					info.interim_info.aes_data.cipher_algo =
+						(uint32_t)algo_con[j].algo;
+					break;
+				}
+			if (j >= RTE_DIM(algo_con))
+				return -EINVAL;
+
+			continue;
+		}
+
+		tmp = strstr(line, OP_STR);
+		if (tmp)
+			continue;
+
+		tmp = strstr(line, KEY_SIZE_STR);
+		if (tmp) {
+			tmp += strlen(KEY_SIZE_STR);
+			if (parser_read_uint32
+					(&info.interim_info.aes_data.key_len,
+							tmp) < 0)
+				return -EINVAL;
+
+			info.interim_info.aes_data.key_len /= 8;
+
+			continue;
+		}
+	}
+
+	info.parse_writeback = parse_test_aes_writeback;
+	info.callbacks = aes_tests_vectors;
+	info.interim_callbacks = aes_tests_interim_vectors;
+	info.writeback_callbacks = aes_writeback_callbacks;
+	info.kat_check = rsp_test_aes_check;
+
+	return 0;
+}
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
index aec5bb9..32af47b 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
@@ -104,6 +104,12 @@ fips_test_parse_header(void)
 		return ret;
 
 	for (i = 0; i < info.nb_vec_lines; i++) {
+		if (strstr(info.vec[i], "AESVS")) {
+			info.algo = FIPS_TEST_ALGO_AES;
+			ret = parse_test_aes_init();
+			if (ret < 0)
+				return ret;
+		}
 
 		tmp = strstr(info.vec[i], "# Config info for ");
 		if (tmp != NULL) {
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
index beb6bed..5ac858d 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
@@ -23,6 +23,7 @@
 #define FAX_FILE_PERFIX		"fax"
 
 enum fips_test_algorithms {
+		FIPS_TEST_ALGO_AES = 0,
 		FIPS_TEST_ALGO_MAX
 };
 
@@ -77,6 +78,21 @@ struct fips_test_callback {
 	struct fips_val *val;
 };
 
+enum fips_aesavs_test_types {
+	AESAVS_TYPE_GFXBOX = 0,
+	AESAVS_TYPE_KEYSBOX,
+	AESAVS_TYPE_VARKEY,
+	AESAVS_TYPE_VARTXT,
+	AESAVS_TYPE_MMT,
+	AESAVS_TYPE_MCT,
+};
+
+struct aesavs_interim_data {
+	enum fips_aesavs_test_types test_type;
+	uint32_t cipher_algo;
+	uint32_t key_len;
+};
+
 struct fips_test_interim_info {
 	FILE *fp_rd;
 	FILE *fp_wr;
@@ -88,6 +104,11 @@ struct fips_test_interim_info {
 	//uint8_t cryptodev_id;
 	char device_name[MAX_STRING_SIZE];
 
+	union {
+		struct aesavs_interim_data aes_data;
+
+	} interim_info;
+
 	enum fips_test_op op;
 
 	const struct fips_test_callback *callbacks;
@@ -118,6 +139,9 @@ void
 fips_test_write_one_case(void);
 
 int
+parse_test_aes_init(void);
+
+int
 parser_read_uint8_hex(uint8_t *value, const char *p);
 
 int
diff --git a/examples/cryptodev_fips_validate/main.c b/examples/cryptodev_fips_validate/main.c
index 4f14b04..98d70b4 100644
--- a/examples/cryptodev_fips_validate/main.c
+++ b/examples/cryptodev_fips_validate/main.c
@@ -329,6 +329,340 @@ 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;
+
+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);
+
+	__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;
+
+	memcpy(iv, vec.iv.val, 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);
+
+		if (!pt) {
+			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
+					-ENOMEM);
+			return -ENOMEM;
+		}
+
+		memcpy(pt, vec.pt.val, vec.pt.len);
+		sym->cipher.data.length = vec.pt.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;
+		}
+
+		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;
+		}
+
+		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);
+
+	return 0;
+}
+
+static int
+prepare_aes_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_cipher_xform *cipher_xform = &xform->cipher;
+
+	xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+
+	cipher_xform->algo = RTE_CRYPTO_CIPHER_AES_CBC;
+	cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_CIPHER_OP_ENCRYPT :
+			RTE_CRYPTO_CIPHER_OP_DECRYPT;
+	cipher_xform->key.data = vec.cipher_auth.key.val;
+	cipher_xform->key.length = vec.cipher_auth.key.len;
+	cipher_xform->iv.length = vec.iv.len;
+	cipher_xform->iv.offset = IV_OFF;
+
+	cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_AES_CBC;
+	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;
+	}
+
+	return 0;
+}
+
+static void
+get_writeback_data(struct fips_val *val)
+{
+	val->val = rte_pktmbuf_mtod(env.mbuf, uint8_t *);
+	val->len = rte_pktmbuf_pkt_len(env.mbuf);
+}
+
+static int
+fips_run_test(void)
+{
+	struct rte_crypto_sym_xform xform = {0};
+	uint16_t n_deqd;
+	int ret;
+
+	ret = test_ops.prepare_xform(&xform);
+	if (ret < 0)
+		return ret;
+
+	env.sess = rte_cryptodev_sym_session_create(env.mpool);
+	if (!env.sess)
+		return -ENOMEM;
+
+	ret = rte_cryptodev_sym_session_init(env.dev_id,
+			env.sess, &xform, env.mpool);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: Init session\n",
+				ret);
+		return ret;
+	}
+
+	ret = test_ops.prepare_op();
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
+				ret);
+		return ret;
+	}
+
+	if (rte_cryptodev_enqueue_burst(env.dev_id, 0, &env.op, 1) < 1) {
+		RTE_LOG(ERR, USER1, "Error: Failed enqueue\n");
+		return ret;
+	}
+
+	do {
+		struct rte_crypto_op *deqd_op;
+
+		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
+				1);
+	} while (n_deqd == 0);
+
+	vec.status = env.op->status;
+
+	rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
+	rte_cryptodev_sym_session_free(env.sess);
+	env.sess = NULL;
+
+	return ret;
+}
+
+static int
+fips_generic_test(void)
+{
+	struct fips_val val;
+	int ret;
+
+	fips_test_write_one_case();
+
+	ret = fips_run_test();
+	if (ret < 0) {
+		if (ret == -EPERM) {
+			fprintf(info.fp_wr, "Bypass\n\n");
+			return 0;
+		}
+
+		return ret;
+	}
+
+	get_writeback_data(&val);
+
+	switch (info.file_type) {
+	case FIPS_TYPE_REQ:
+	case FIPS_TYPE_RSP:
+		if (info.parse_writeback == NULL)
+			return -EPERM;
+		ret = info.parse_writeback(&val);
+		if (ret < 0)
+			return ret;
+		break;
+	case FIPS_TYPE_FAX:
+		if (info.kat_check == NULL)
+			return -EPERM;
+		ret = info.kat_check(&val);
+		if (ret < 0)
+			return ret;
+		break;
+	}
+
+	fprintf(info.fp_wr, "\n");
+
+	return 0;
+}
+
+static int
+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;
+	uint8_t prev_out[AES_BLOCK_SIZE] = {0};
+	uint8_t prev_in[AES_BLOCK_SIZE] = {0};
+	uint32_t i, j, k;
+	int ret;
+
+	for (i = 0; i < AES_EXTERN_ITER; i++) {
+		if (i != 0)
+			update_info_vec(i);
+
+		fips_test_write_one_case();
+
+		for (j = 0; j < AES_INTERN_ITER; j++) {
+			ret = fips_run_test();
+			if (ret < 0) {
+				if (ret == -EPERM) {
+					fprintf(info.fp_wr, "Bypass\n");
+					return 0;
+				}
+
+				return ret;
+			}
+
+			get_writeback_data(&val);
+
+			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
+				memcpy(prev_in, vec.ct.val, AES_BLOCK_SIZE);
+
+			if (j == 0) {
+				memcpy(prev_out, val.val, AES_BLOCK_SIZE);
+
+				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+					memcpy(vec.pt.val, vec.iv.val,
+							AES_BLOCK_SIZE);
+					memcpy(vec.iv.val, val.val,
+							AES_BLOCK_SIZE);
+				} else {
+					memcpy(vec.ct.val, vec.iv.val,
+							AES_BLOCK_SIZE);
+					memcpy(vec.iv.val, prev_in,
+							AES_BLOCK_SIZE);
+				}
+				continue;
+			}
+
+			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+				memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
+				memcpy(vec.pt.val, prev_out, AES_BLOCK_SIZE);
+			} else {
+				memcpy(vec.iv.val, prev_in, AES_BLOCK_SIZE);
+				memcpy(vec.ct.val, prev_out, AES_BLOCK_SIZE);
+			}
+
+			if (j == AES_INTERN_ITER - 1)
+				continue;
+
+			memcpy(prev_out, val.val, AES_BLOCK_SIZE);
+		}
+
+		info.parse_writeback(&val);
+		fprintf(info.fp_wr, "\n");
+
+		if (i == AES_EXTERN_ITER - 1)
+			continue;
+
+		/** update key */
+		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
+		for (k = 0; k < vec.cipher_auth.key.len; k++) {
+			switch (vec.cipher_auth.key.len) {
+			case 16:
+				val_key.val[k] ^= val.val[k];
+				break;
+			case 24:
+				if (k < 8)
+					val_key.val[k] ^= prev_out[k + 8];
+				else
+					val_key.val[k] ^= val.val[k - 8];
+				break;
+			case 32:
+				if (k < 16)
+					val_key.val[k] ^= prev_out[k];
+				else
+					val_key.val[k] ^= val.val[k - 16];
+				break;
+			default:
+				return -1;
+			}
+		}
+
+		if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
+			memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
+	}
+
+	return 0;
+}
+
+static int
+init_test_ops(void)
+{
+	switch (info.algo) {
+	case FIPS_TEST_ALGO_AES:
+		test_ops.prepare_op = prepare_cipher_op;
+		test_ops.prepare_xform  = prepare_aes_xform;
+		if (info.interim_info.aes_data.test_type == AESAVS_TYPE_MCT)
+			test_ops.test = fips_mct_aes_test;
+		else
+			test_ops.test = fips_generic_test;
+		break;
+
+	default:
+		return -1;
+	}
+
+	return 0;
+}
+
 static void
 print_test_block(void)
 {
@@ -345,7 +679,14 @@ fips_test_one_file(void)
 {
 	int fetch_ret = 0, ret;
 
-	while (fetch_ret == 0) {
+
+	ret = init_test_ops();
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: Init test op\n", ret);
+		return ret;
+	}
+
+	while (ret >= 0 && fetch_ret == 0) {
 		fetch_ret = fips_test_fetch_one_block();
 		if (fetch_ret < 0) {
 			RTE_LOG(ERR, USER1, "Error %i: Fetch block\n",
@@ -365,6 +706,7 @@ fips_test_one_file(void)
 		ret = fips_test_parse_one_case();
 		switch (ret) {
 		case 0:
+			ret = test_ops.test();
 			if (ret == 0)
 				break;
 			RTE_LOG(ERR, USER1, "Error %i: test block\n",
@@ -385,4 +727,6 @@ fips_test_one_file(void)
 
 	fips_test_clear();
 
+	return ret;
+
 }
diff --git a/examples/cryptodev_fips_validate/meson.build b/examples/cryptodev_fips_validate/meson.build
index e417733..d04e9bb 100644
--- a/examples/cryptodev_fips_validate/meson.build
+++ b/examples/cryptodev_fips_validate/meson.build
@@ -9,6 +9,7 @@
 deps += ['cryptodev', 'bus_pci']
 allow_experimental_apis = true
 sources = files(
+	'cryptodev_fips_parse_aes.c',
 	'cryptodev_fips_parse_validate.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v4 3/8] examples: add hmac parser
  2018-10-12 14:44 [dpdk-dev] [PATCH v4 0/8] FIPS validation capability Marko Kovacevic
  2018-10-12 14:44 ` [dpdk-dev] [PATCH v4 1/8] examples: add fips validation into examples Marko Kovacevic
  2018-10-12 14:44 ` [dpdk-dev] [PATCH v4 2/8] examples: add aes parser and enablement for test types Marko Kovacevic
@ 2018-10-12 14:44 ` Marko Kovacevic
  2018-10-12 14:44 ` [dpdk-dev] [PATCH v4 4/8] examples: add TDES parser and enablement for test types Marko Kovacevic
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-12 14:44 UTC (permalink / raw)
  To: dev; +Cc: roy.fan.zhang, akhil.goyal, arkadiuszx.kusztal, Marko Kovacevic

Added enablement for HMAC parser, to allow the
application to parser the hmac request files and to validate all
tests supported

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
---
 examples/cryptodev_fips_validate/Makefile          |   1 +
 .../cryptodev_fips_parse_hmac.c                    | 105 +++++++++++++++++++++
 .../cryptodev_fips_parse_validate.c                |   5 +
 .../cryptodev_fips_validate.h                      |   9 ++
 examples/cryptodev_fips_validate/main.c            | 103 ++++++++++++++++++++
 examples/cryptodev_fips_validate/meson.build       |   1 +
 6 files changed, 224 insertions(+)
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_hmac.c

diff --git a/examples/cryptodev_fips_validate/Makefile b/examples/cryptodev_fips_validate/Makefile
index f058081..50be23c 100644
--- a/examples/cryptodev_fips_validate/Makefile
+++ b/examples/cryptodev_fips_validate/Makefile
@@ -6,6 +6,7 @@ APP = cryptodev_fips_validate_app
 
 # all source are stored in SRCS-y
 SRCS-y := cryptodev_fips_parse_aes.c
+SRCS-y += cryptodev_fips_parse_hmac.c
 SRCS-y += cryptodev_fips_parse_validate.c
 SRCS-y += main.c
 
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_hmac.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_hmac.c
new file mode 100644
index 0000000..2fbc246
--- /dev/null
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_hmac.c
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+
+#include <rte_cryptodev.h>
+
+#include "cryptodev_fips_validate.h"
+
+#define ALGO_PREFIX	"[L="
+#define KEYLEN_STR	"Klen = "
+#define TAGLEN_STR	"Tlen = "
+
+#define COUNT_STR	"Count = "
+#define KEY_STR		"Key = "
+#define PT_STR		"Msg = "
+#define TAG_STR		"Mac = "
+
+struct hash_size_conversion {
+	const char *str;
+	enum rte_crypto_auth_algorithm algo;
+} hsc[] = {
+		{"20", RTE_CRYPTO_AUTH_SHA1_HMAC},
+		{"28", RTE_CRYPTO_AUTH_SHA224_HMAC},
+		{"32", RTE_CRYPTO_AUTH_SHA256_HMAC},
+		{"48", RTE_CRYPTO_AUTH_SHA384_HMAC},
+		{"64", RTE_CRYPTO_AUTH_SHA512_HMAC},
+};
+
+static int
+parse_interim_algo(__attribute__((__unused__)) const char *key,
+		char *text,
+		__attribute__((__unused__)) struct fips_val *val)
+{
+
+	uint32_t i;
+
+	for (i = 0; i < RTE_DIM(hsc); i++) {
+		if (strstr(text, hsc[i].str)) {
+			info.interim_info.hmac_data.algo = hsc[i].algo;
+			break;
+		}
+	}
+
+	if (i == RTE_DIM(hsc))
+		return -1;
+
+	return 0;
+}
+
+struct fips_test_callback hmac_tests_vectors[] = {
+		{KEYLEN_STR, parser_read_uint32_val, &vec.cipher_auth.key},
+		{TAGLEN_STR, parser_read_uint32_val, &vec.cipher_auth.digest},
+		{KEY_STR, parse_uint8_hex_str, &vec.cipher_auth.key},
+		{PT_STR, parse_uint8_hex_str, &vec.pt},
+		{TAG_STR, parse_uint8_hex_str, &vec.cipher_auth.digest},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback hmac_tests_interim_vectors[] = {
+		{ALGO_PREFIX, parse_interim_algo, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+static int
+parse_test_hmac_writeback(struct fips_val *val)
+{
+	struct fips_val val_local;
+
+	fprintf(info.fp_wr, "%s", TAG_STR);
+
+	val_local.val = val->val + vec.pt.len;
+	val_local.len = vec.cipher_auth.digest.len;
+
+	parse_write_hex_str(&val_local);
+	return 0;
+}
+
+static int
+rsp_test_hmac_check(struct fips_val *val)
+{
+	if (memcmp(val->val + vec.pt.len, vec.cipher_auth.digest.val,
+			vec.cipher_auth.digest.len) == 0)
+		fprintf(info.fp_wr, "Success\n");
+	else
+		fprintf(info.fp_wr, "Failed\n");
+
+	return 0;
+}
+
+int
+parse_test_hmac_init(void)
+{
+	info.op = FIPS_TEST_ENC_AUTH_GEN;
+	info.parse_writeback = parse_test_hmac_writeback;
+	info.callbacks = hmac_tests_vectors;
+	info.interim_callbacks = hmac_tests_interim_vectors;
+	info.writeback_callbacks = NULL;
+	info.kat_check = rsp_test_hmac_check;
+
+	return 0;
+}
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
index 32af47b..f1cd802 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
@@ -109,6 +109,11 @@ fips_test_parse_header(void)
 			ret = parse_test_aes_init();
 			if (ret < 0)
 				return ret;
+		} else if (strstr(info.vec[i], "HMAC")) {
+			info.algo = FIPS_TEST_ALGO_HMAC;
+			ret = parse_test_hmac_init();
+			if (ret < 0)
+				return ret;
 		}
 
 		tmp = strstr(info.vec[i], "# Config info for ");
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
index 5ac858d..3cda9fe 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
@@ -24,6 +24,7 @@
 
 enum fips_test_algorithms {
 		FIPS_TEST_ALGO_AES = 0,
+		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_MAX
 };
 
@@ -93,6 +94,10 @@ struct aesavs_interim_data {
 	uint32_t key_len;
 };
 
+struct hmac_interim_data {
+	enum rte_crypto_auth_algorithm algo;
+};
+
 struct fips_test_interim_info {
 	FILE *fp_rd;
 	FILE *fp_wr;
@@ -106,6 +111,7 @@ struct fips_test_interim_info {
 
 	union {
 		struct aesavs_interim_data aes_data;
+		struct hmac_interim_data hmac_data;
 
 	} interim_info;
 
@@ -142,6 +148,9 @@ int
 parse_test_aes_init(void);
 
 int
+parse_test_hmac_init(void);
+
+int
 parser_read_uint8_hex(uint8_t *value, const char *p);
 
 int
diff --git a/examples/cryptodev_fips_validate/main.c b/examples/cryptodev_fips_validate/main.c
index 98d70b4..a165576 100644
--- a/examples/cryptodev_fips_validate/main.c
+++ b/examples/cryptodev_fips_validate/main.c
@@ -401,6 +401,67 @@ prepare_cipher_op(void)
 }
 
 static int
+prepare_auth_op(void)
+{
+	struct rte_crypto_sym_op *sym = env.op->sym;
+
+	__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;
+
+	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.cipher_auth.digest.len);
+
+		if (!pt) {
+			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
+					-ENOMEM);
+			return -ENOMEM;
+		}
+
+		memcpy(pt, vec.pt.val, vec.pt.len);
+		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);
+
+	} 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 + vec.cipher_auth.digest.len);
+
+		if (!ct) {
+			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
+					-ENOMEM);
+			return -ENOMEM;
+		}
+
+		memcpy(ct, vec.ct.val, vec.ct.len);
+		sym->auth.data.length = vec.ct.len;
+		sym->auth.digest.data = vec.cipher_auth.digest.val;
+		sym->auth.digest.phys_addr = rte_malloc_virt2iova(
+				sym->auth.digest.data);
+	}
+
+	rte_crypto_op_attach_sym_session(env.op, env.sess);
+}
+
+static int
 prepare_aes_xform(struct rte_crypto_sym_xform *xform)
 {
 	const struct rte_cryptodev_symmetric_capability *cap;
@@ -440,6 +501,43 @@ prepare_aes_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_hmac_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 = info.interim_info.hmac_data.algo;
+	auth_xform->op = RTE_CRYPTO_AUTH_OP_GENERATE;
+	auth_xform->digest_length = vec.cipher_auth.digest.len;
+	auth_xform->key.data = vec.cipher_auth.key.val;
+	auth_xform->key.length = vec.cipher_auth.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 void
 get_writeback_data(struct fips_val *val)
 {
@@ -655,6 +753,11 @@ init_test_ops(void)
 		else
 			test_ops.test = fips_generic_test;
 		break;
+	case FIPS_TEST_ALGO_HMAC:
+		test_ops.prepare_op = prepare_auth_op;
+		test_ops.prepare_xform = prepare_hmac_xform;
+		test_ops.test = fips_generic_test;
+		break;
 
 	default:
 		return -1;
diff --git a/examples/cryptodev_fips_validate/meson.build b/examples/cryptodev_fips_validate/meson.build
index d04e9bb..dcf90bb 100644
--- a/examples/cryptodev_fips_validate/meson.build
+++ b/examples/cryptodev_fips_validate/meson.build
@@ -10,6 +10,7 @@ deps += ['cryptodev', 'bus_pci']
 allow_experimental_apis = true
 sources = files(
 	'cryptodev_fips_parse_aes.c',
+	'cryptodev_fips_parse_hmac.c',
 	'cryptodev_fips_parse_validate.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v4 4/8] examples: add TDES parser and enablement for test types
  2018-10-12 14:44 [dpdk-dev] [PATCH v4 0/8] FIPS validation capability Marko Kovacevic
                   ` (2 preceding siblings ...)
  2018-10-12 14:44 ` [dpdk-dev] [PATCH v4 3/8] examples: add hmac parser Marko Kovacevic
@ 2018-10-12 14:44 ` Marko Kovacevic
  2018-10-12 14:44 ` [dpdk-dev] [PATCH v4 5/8] examples: add gcm parser Marko Kovacevic
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-12 14:44 UTC (permalink / raw)
  To: dev; +Cc: roy.fan.zhang, akhil.goyal, arkadiuszx.kusztal, Marko Kovacevic

Added enablement for TDES parser, to allow the
application to parser the TDES request files and to validate all
test types supported.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
---
 examples/cryptodev_fips_validate/Makefile          |   1 +
 .../cryptodev_fips_parse_3des.c                    | 259 +++++++++++++++++++++
 .../cryptodev_fips_parse_aes.c                     |   2 +
 .../cryptodev_fips_parse_validate.c                |   5 +
 .../cryptodev_fips_validate.h                      |  21 ++
 examples/cryptodev_fips_validate/main.c            | 175 ++++++++++++++
 examples/cryptodev_fips_validate/meson.build       |   1 +
 7 files changed, 464 insertions(+)
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c

diff --git a/examples/cryptodev_fips_validate/Makefile b/examples/cryptodev_fips_validate/Makefile
index 50be23c..54ea43f 100644
--- a/examples/cryptodev_fips_validate/Makefile
+++ b/examples/cryptodev_fips_validate/Makefile
@@ -7,6 +7,7 @@ APP = cryptodev_fips_validate_app
 # all source are stored in SRCS-y
 SRCS-y := cryptodev_fips_parse_aes.c
 SRCS-y += cryptodev_fips_parse_hmac.c
+SRCS-y += cryptodev_fips_parse_3des.c
 SRCS-y += cryptodev_fips_parse_validate.c
 SRCS-y += main.c
 
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c
new file mode 100644
index 0000000..82e9132
--- /dev/null
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c
@@ -0,0 +1,259 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include <rte_malloc.h>
+#include <rte_cryptodev.h>
+
+#include "cryptodev_fips_validate.h"
+
+#define NEW_LINE_STR	"#"
+#define TEST_TYPE_KEY	" for CBC"
+#define TEST_CBCI_KEY	" for CBCI"
+
+#define ENC_STR		"[ENCRYPT]"
+#define DEC_STR		"[DECRYPT]"
+
+#define COUNT_STR	"COUNT = "
+#define KEY1_STR	"KEY1 = "
+#define KEY2_STR	"KEY2 = "
+#define KEY3_STR	"KEY3 = "
+
+#define KEYS_STR	"KEYs = "
+#define IV_STR		"IV = "
+#define PT_STR		"PLAINTEXT = "
+#define CT_STR		"CIPHERTEXT = "
+#define NK_STR		"NumKeys = "
+
+#define SET_STR		" = "
+
+#define PLAIN_TEXT	0
+#define CIPHER_TEXT	1
+#define KEY_TEXT	2
+#define IV_TEXT		3
+
+#define DEVICE_STR	"# Config Info for : "
+
+struct {
+	uint32_t type;
+	const char *desc;
+} test_types[] = {
+		{TDES_INVERSE_PERMUTATION, "INVERSE PERMUTATION"},
+		{TDES_PERMUTATION, "PERMUTATION OPERATION"},
+		{TDES_SUBSTITUTION_TABLE, "SUBSTITUTION TABLE"},
+		{TDES_VARIABLE_KEY, "VARIABLE KEY"},
+		{TDES_VARIABLE_TEXT, "VARIABLE PLAINTEXT/CIPHERTEXT"},
+		{TDES_VARIABLE_TEXT, "KAT"},
+		{TDES_MCT, "Monte Carlo (Modes) Test"},
+		{TDES_MMT, "Multi block Message Test"},
+};
+
+static int
+writeback_tdes_hex_str(const char *key, char *dst, struct fips_val *val);
+
+static int
+parse_3des_uint8_hex_str(const char *key, char *src, struct fips_val *val);
+
+static int
+parse_tdes_interim(const char *key,
+		__attribute__((__unused__)) char *text,
+		struct fips_val *val);
+
+struct fips_test_callback tdes_tests_vectors[] = {
+		{KEYS_STR, parse_3des_uint8_hex_str, &vec.cipher_auth.key},
+		{KEY1_STR, parse_3des_uint8_hex_str, &vec.cipher_auth.key},
+		{KEY2_STR, parse_3des_uint8_hex_str, &vec.cipher_auth.key},
+		{KEY3_STR, parse_3des_uint8_hex_str, &vec.cipher_auth.key},
+		{IV_STR, parse_uint8_hex_str, &vec.iv},
+		{PT_STR, parse_uint8_hex_str, &vec.pt},
+		{CT_STR, parse_uint8_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback tdes_tests_interim_vectors[] = {
+		{ENC_STR, parse_tdes_interim, NULL},
+		{DEC_STR, parse_tdes_interim, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback tdes_writeback_callbacks[] = {
+		/** First element is used to pass COUNT string */
+		{COUNT_STR, NULL, NULL},
+		{IV_STR, writeback_hex_str, &vec.iv},
+		{KEY1_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
+		{KEY2_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
+		{KEY3_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
+		{KEYS_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
+		{PT_STR, writeback_hex_str, &vec.pt},
+		{CT_STR, writeback_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+static int
+parse_tdes_interim(const char *key,
+		__attribute__((__unused__)) char *text,
+		__attribute__((__unused__)) struct fips_val *val)
+{
+	if (strstr(key, ENC_STR))
+		info.op = FIPS_TEST_ENC_AUTH_GEN;
+	else if (strstr(key, DEC_STR))
+		info.op = FIPS_TEST_DEC_AUTH_VERIF;
+	else if (strstr(NK_STR, "NumKeys = 1"))
+		info.interim_info.tdes_data.nb_keys = 1;
+	else if (strstr(NK_STR, "NumKeys = 2"))
+		info.interim_info.tdes_data.nb_keys = 2;
+	else if (strstr(NK_STR, "NumKeys = 3"))
+		info.interim_info.tdes_data.nb_keys = 3;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int
+parse_3des_uint8_hex_str(const char *key, char *src, struct fips_val *val)
+{
+	uint8_t tmp_key[24] = {0};
+	uint32_t len, i;
+
+	src += strlen(key);
+
+	len = strlen(src) / 2;
+
+	if (val->val) {
+		memcpy(tmp_key, val->val, val->len);
+		rte_free(val->val);
+	}
+
+	val->val = rte_zmalloc(NULL, 24, 0);
+	if (!val->val)
+		return -1;
+
+	memcpy(val->val, tmp_key, 24);
+
+	if (strstr(key, KEYS_STR)) {
+		for (i = 0; i < len; i++) {
+			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
+
+			if (parser_read_uint8_hex(&val->val[i], byte) < 0)
+				return -EINVAL;
+		}
+
+		memcpy(val->val + 8, val->val, 8);
+		memcpy(val->val + 16, val->val, 8);
+
+	} else if (strstr(key, KEY1_STR)) {
+		for (i = 0; i < len; i++) {
+			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
+
+			if (parser_read_uint8_hex(&val->val[i], byte) < 0)
+				return -EINVAL;
+		}
+
+		if (info.interim_info.tdes_data.nb_keys == 2)
+			memcpy(val->val + 16, val->val, 8);
+
+	} else if (strstr(key, KEY2_STR)) {
+		for (i = 0; i < len; i++) {
+			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
+
+			if (parser_read_uint8_hex(&val->val[i + 8], byte) < 0)
+				return -EINVAL;
+		}
+
+	} else if (strstr(key, KEY3_STR)) {
+		for (i = 0; i < len; i++) {
+			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
+
+			if (parser_read_uint8_hex(&val->val[i + 16], byte) < 0)
+				return -EINVAL;
+		}
+	} else
+		return -EINVAL;
+
+	val->len = 24;
+
+	return 0;
+}
+
+static int
+parse_test_tdes_writeback(struct fips_val *val)
+{
+
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN)
+		fprintf(info.fp_wr, "%s", CT_STR);
+	else
+		fprintf(info.fp_wr, "%s", PT_STR);
+
+	parse_write_hex_str(val);
+
+	return 0;
+
+}
+
+static int
+writeback_tdes_hex_str(const char *key, char *dst, struct fips_val *val)
+{
+	struct fips_val tmp_val;
+
+	tmp_val.len = 8;
+
+	if (strstr(key, KEY1_STR))
+		tmp_val.val = val->val;
+	else if (strstr(key, KEY2_STR))
+		tmp_val.val = val->val + 8;
+	else if (strstr(key, KEY3_STR))
+		tmp_val.val = val->val + 16;
+
+	return writeback_hex_str(key, dst, &tmp_val);
+}
+
+static int
+rsp_test_tdes_check(struct fips_val *val)
+{
+	struct fips_val *data;
+
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN)
+		data = &vec.ct;
+	else
+		data = &vec.pt;
+
+	if (memcmp(val->val, data->val, val->len) == 0)
+		fprintf(info.fp_wr, "Success\n");
+	else
+		fprintf(info.fp_wr, "Failed\n");
+
+	return 0;
+}
+
+int
+parse_test_tdes_init(void)
+{
+	uint32_t i;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		char *line = info.vec[i];
+		uint32_t j;
+
+		if (strstr(line, TEST_CBCI_KEY))
+			return -EPERM;
+
+		for (j = 0; j < RTE_DIM(test_types); j++)
+			if (strstr(line, test_types[j].desc)) {
+				info.interim_info.tdes_data.test_type =
+						test_types[j].type;
+				break;
+			}
+	}
+
+	info.parse_writeback = parse_test_tdes_writeback;
+	info.callbacks = tdes_tests_vectors;
+	info.interim_callbacks = tdes_tests_interim_vectors;
+	info.writeback_callbacks = tdes_writeback_callbacks;
+	info.kat_check = rsp_test_tdes_check;
+
+	return 0;
+}
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c
index 39dbd6f..cc27754 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c
@@ -33,6 +33,8 @@ struct {
 		{AESAVS_TYPE_KEYSBOX, "KeySbox"},
 		{AESAVS_TYPE_VARKEY, "VarKey"},
 		{AESAVS_TYPE_VARTXT, "VarTxt"},
+		{TDES_VARIABLE_TEXT, "VARIABLE PLAINTEXT/CIPHERTEXT"},
+		{TDES_VARIABLE_TEXT, "KAT"},
 		{AESAVS_TYPE_MMT, "MMT"},
 		{AESAVS_TYPE_MCT, "MCT"},
 };
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
index f1cd802..bb396e5 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
@@ -114,6 +114,11 @@ fips_test_parse_header(void)
 			ret = parse_test_hmac_init();
 			if (ret < 0)
 				return ret;
+		} else if (strstr(info.vec[i], "TDES")) {
+			info.algo = FIPS_TEST_ALGO_TDES;
+			ret = parse_test_tdes_init();
+			if (ret < 0)
+				return 0;
 		}
 
 		tmp = strstr(info.vec[i], "# Config info for ");
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
index 3cda9fe..c9b11dd 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
@@ -25,6 +25,7 @@
 enum fips_test_algorithms {
 		FIPS_TEST_ALGO_AES = 0,
 		FIPS_TEST_ALGO_HMAC,
+		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_MAX
 };
 
@@ -88,6 +89,17 @@ enum fips_aesavs_test_types {
 	AESAVS_TYPE_MCT,
 };
 
+enum fips_tdes_test_types {
+	TDES_INVERSE_PERMUTATION = 0,
+	TDES_PERMUTATION,
+	TDES_SUBSTITUTION_TABLE,
+	TDES_VARIABLE_KEY,
+	TDES_VARIABLE_TEXT,
+	TDES_KAT,
+	TDES_MCT, /* Monte Carlo (Modes) Test */
+	TDES_MMT /* Multi block Message Test */
+};
+
 struct aesavs_interim_data {
 	enum fips_aesavs_test_types test_type;
 	uint32_t cipher_algo;
@@ -98,6 +110,11 @@ struct hmac_interim_data {
 	enum rte_crypto_auth_algorithm algo;
 };
 
+struct tdes_interim_data {
+	enum fips_tdes_test_types test_type;
+	uint32_t nb_keys;
+};
+
 struct fips_test_interim_info {
 	FILE *fp_rd;
 	FILE *fp_wr;
@@ -112,6 +129,7 @@ struct fips_test_interim_info {
 	union {
 		struct aesavs_interim_data aes_data;
 		struct hmac_interim_data hmac_data;
+		struct tdes_interim_data tdes_data;
 
 	} interim_info;
 
@@ -148,6 +166,9 @@ int
 parse_test_aes_init(void);
 
 int
+parse_test_tdes_init(void);
+
+int
 parse_test_hmac_init(void);
 
 int
diff --git a/examples/cryptodev_fips_validate/main.c b/examples/cryptodev_fips_validate/main.c
index a165576..78add5a 100644
--- a/examples/cryptodev_fips_validate/main.c
+++ b/examples/cryptodev_fips_validate/main.c
@@ -502,6 +502,46 @@ prepare_aes_xform(struct rte_crypto_sym_xform *xform)
 }
 
 static int
+prepare_tdes_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_cipher_xform *cipher_xform = &xform->cipher;
+
+	xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+
+	cipher_xform->algo = RTE_CRYPTO_CIPHER_3DES_CBC;
+	cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_CIPHER_OP_ENCRYPT :
+			RTE_CRYPTO_CIPHER_OP_DECRYPT;
+	cipher_xform->key.data = vec.cipher_auth.key.val;
+	cipher_xform->key.length = vec.cipher_auth.key.len;
+	cipher_xform->iv.length = vec.iv.len;
+	cipher_xform->iv.offset = IV_OFF;
+
+	cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_3DES_CBC;
+	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;
+	}
+
+	return 0;
+}
+
+static int
 prepare_hmac_xform(struct rte_crypto_sym_xform *xform)
 {
 	const struct rte_cryptodev_symmetric_capability *cap;
@@ -640,6 +680,133 @@ fips_generic_test(void)
 }
 
 static int
+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;
+	uint8_t prev_out[TDES_BLOCK_SIZE];
+	uint8_t prev_prev_out[TDES_BLOCK_SIZE];
+	uint8_t prev_in[TDES_BLOCK_SIZE];
+	uint32_t i, j, k;
+	int ret;
+
+	for (i = 0; i < TDES_EXTERN_ITER; i++) {
+		if (i != 0)
+			update_info_vec(i);
+
+		fips_test_write_one_case();
+
+		for (j = 0; j < TDES_INTERN_ITER; j++) {
+			ret = fips_run_test();
+			if (ret < 0) {
+				if (ret == -EPERM) {
+					fprintf(info.fp_wr, "Bypass\n");
+					return 0;
+				}
+
+				return ret;
+			}
+
+			get_writeback_data(&val);
+
+			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
+				memcpy(prev_in, vec.ct.val, TDES_BLOCK_SIZE);
+
+			if (j == 0) {
+				memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
+
+				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+					memcpy(vec.pt.val, vec.iv.val,
+							TDES_BLOCK_SIZE);
+					memcpy(vec.iv.val, val.val,
+							TDES_BLOCK_SIZE);
+				} else {
+					memcpy(vec.iv.val, vec.ct.val,
+							TDES_BLOCK_SIZE);
+					memcpy(vec.ct.val, val.val,
+							TDES_BLOCK_SIZE);
+				}
+				continue;
+			}
+
+			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+				memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
+				memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
+			} else {
+				memcpy(vec.iv.val, vec.ct.val, TDES_BLOCK_SIZE);
+				memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
+			}
+
+			if (j == TDES_INTERN_ITER - 1)
+				continue;
+
+			memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
+
+			if (j == TDES_INTERN_ITER - 3)
+				memcpy(prev_prev_out, val.val, TDES_BLOCK_SIZE);
+		}
+
+		info.parse_writeback(&val);
+		fprintf(info.fp_wr, "\n");
+
+		if (i == TDES_EXTERN_ITER - 1)
+			continue;
+
+		/** update key */
+		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
+
+		if (info.interim_info.tdes_data.nb_keys == 0) {
+			if (memcmp(val_key.val, val_key.val + 8, 8) == 0)
+				info.interim_info.tdes_data.nb_keys = 1;
+			else if (memcmp(val_key.val, val_key.val + 16, 8) == 0)
+				info.interim_info.tdes_data.nb_keys = 2;
+			else
+				info.interim_info.tdes_data.nb_keys = 3;
+
+		}
+
+		for (k = 0; k < TDES_BLOCK_SIZE; k++) {
+
+			switch (info.interim_info.tdes_data.nb_keys) {
+			case 3:
+				val_key.val[k] ^= val.val[k];
+				val_key.val[k + 8] ^= prev_out[k];
+				val_key.val[k + 16] ^= prev_prev_out[k];
+				break;
+			case 2:
+				val_key.val[k] ^= val.val[k];
+				val_key.val[k + 8] ^= prev_out[k];
+				val_key.val[k + 16] ^= val.val[k];
+				break;
+			default: /* case 1 */
+				val_key.val[k] ^= val.val[k];
+				val_key.val[k + 8] ^= val.val[k];
+				val_key.val[k + 16] ^= val.val[k];
+				break;
+			}
+
+		}
+
+		for (k = 0; k < 24; k++)
+			val_key.val[k] = (__builtin_popcount(val_key.val[k]) &
+					0x1) ?
+					val_key.val[k] : (val_key.val[k] ^ 0x1);
+
+		if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+			memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
+			memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
+		} else {
+			memcpy(vec.iv.val, prev_out, TDES_BLOCK_SIZE);
+			memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
+		}
+	}
+
+	return 0;
+}
+
+static int
 fips_mct_aes_test(void)
 {
 #define AES_BLOCK_SIZE	16
@@ -758,6 +925,14 @@ init_test_ops(void)
 		test_ops.prepare_xform = prepare_hmac_xform;
 		test_ops.test = fips_generic_test;
 		break;
+	case FIPS_TEST_ALGO_TDES:
+		test_ops.prepare_op = prepare_cipher_op;
+		test_ops.prepare_xform  = prepare_tdes_xform;
+		if (info.interim_info.tdes_data.test_type == TDES_MCT)
+			test_ops.test = fips_mct_tdes_test;
+		else
+			test_ops.test = fips_generic_test;
+		break;
 
 	default:
 		return -1;
diff --git a/examples/cryptodev_fips_validate/meson.build b/examples/cryptodev_fips_validate/meson.build
index dcf90bb..a18e76d 100644
--- a/examples/cryptodev_fips_validate/meson.build
+++ b/examples/cryptodev_fips_validate/meson.build
@@ -11,6 +11,7 @@ allow_experimental_apis = true
 sources = files(
 	'cryptodev_fips_parse_aes.c',
 	'cryptodev_fips_parse_hmac.c',
+	'cryptodev_fips_parse_3des.c',
 	'cryptodev_fips_parse_validate.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v4 5/8] examples: add gcm parser
  2018-10-12 14:44 [dpdk-dev] [PATCH v4 0/8] FIPS validation capability Marko Kovacevic
                   ` (3 preceding siblings ...)
  2018-10-12 14:44 ` [dpdk-dev] [PATCH v4 4/8] examples: add TDES parser and enablement for test types Marko Kovacevic
@ 2018-10-12 14:44 ` Marko Kovacevic
  2018-10-12 14:44 ` [dpdk-dev] [PATCH v4 6/8] examples: add cmac parser and enablement for test types Marko Kovacevic
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-12 14:44 UTC (permalink / raw)
  To: dev; +Cc: roy.fan.zhang, akhil.goyal, arkadiuszx.kusztal, Marko Kovacevic

Added enablement for GCM parser, to allow the
application to parser the GCM request file and to validate all
tests supported.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
---
 examples/cryptodev_fips_validate/Makefile          |   1 +
 .../cryptodev_fips_parse_gcm.c                     | 125 +++++++++++++++++++++
 .../cryptodev_fips_parse_validate.c                |   5 +
 .../cryptodev_fips_validate.h                      |   4 +
 examples/cryptodev_fips_validate/main.c            | 116 ++++++++++++++++++-
 examples/cryptodev_fips_validate/meson.build       |   1 +
 6 files changed, 251 insertions(+), 1 deletion(-)
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_gcm.c

diff --git a/examples/cryptodev_fips_validate/Makefile b/examples/cryptodev_fips_validate/Makefile
index 54ea43f..1eb0108 100644
--- a/examples/cryptodev_fips_validate/Makefile
+++ b/examples/cryptodev_fips_validate/Makefile
@@ -8,6 +8,7 @@ APP = cryptodev_fips_validate_app
 SRCS-y := cryptodev_fips_parse_aes.c
 SRCS-y += cryptodev_fips_parse_hmac.c
 SRCS-y += cryptodev_fips_parse_3des.c
+SRCS-y += cryptodev_fips_parse_gcm.c
 SRCS-y += cryptodev_fips_parse_validate.c
 SRCS-y += main.c
 
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_gcm.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_gcm.c
new file mode 100644
index 0000000..6999dad
--- /dev/null
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_gcm.c
@@ -0,0 +1,125 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+
+#include <rte_cryptodev.h>
+
+#include "cryptodev_fips_validate.h"
+
+#define NEW_LINE_STR	"#"
+#define OP_STR		"GCM "
+
+#define PARAM_PREFIX	"["
+#define KEYLEN_STR	"Keylen = "
+#define IVLEN_STR	"IVlen = "
+#define PTLEN_STR	"PTlen = "
+#define AADLEN_STR	"AADlen = "
+#define TAGLEN_STR	"Taglen = "
+
+#define COUNT_STR	"Count = "
+#define KEY_STR		"Key = "
+#define IV_STR		"IV = "
+#define PT_STR		"PT = "
+#define CT_STR		"CT = "
+#define TAG_STR		"Tag = "
+#define AAD_STR		"AAD = "
+
+#define OP_ENC_STR	"Encrypt"
+#define OP_DEC_STR	"Decrypt"
+
+#define NEG_TEST_STR	"FAIL"
+
+struct fips_test_callback gcm_dec_vectors[] = {
+		{KEY_STR, parse_uint8_known_len_hex_str, &vec.cipher_auth.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.cipher_auth.aad},
+		{TAG_STR, parse_uint8_known_len_hex_str,
+				&vec.cipher_auth.digest},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+struct fips_test_callback gcm_interim_vectors[] = {
+		{KEYLEN_STR, parser_read_uint32_bit_val, &vec.cipher_auth.key},
+		{IVLEN_STR, parser_read_uint32_bit_val, &vec.iv},
+		{PTLEN_STR, parser_read_uint32_bit_val, &vec.pt},
+		{AADLEN_STR, parser_read_uint32_bit_val, &vec.cipher_auth.aad},
+		{TAGLEN_STR, parser_read_uint32_bit_val,
+				&vec.cipher_auth.digest},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback gcm_enc_vectors[] = {
+		{KEY_STR, parse_uint8_known_len_hex_str, &vec.cipher_auth.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.cipher_auth.aad},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+static int
+parse_test_gcm_writeback(struct fips_val *val)
+{
+	struct fips_val tmp_val;
+
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+		fprintf(info.fp_wr, "%s", CT_STR);
+
+		tmp_val.val = val->val;
+		tmp_val.len = vec.pt.len;
+
+		parse_write_hex_str(&tmp_val);
+
+		fprintf(info.fp_wr, "%s", TAG_STR);
+
+		tmp_val.val = val->val + vec.pt.len;
+		tmp_val.len = val->len - vec.pt.len;
+
+		parse_write_hex_str(&tmp_val);
+	} else {
+		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS) {
+			fprintf(info.fp_wr, "%s", PT_STR);
+
+			tmp_val.val = val->val;
+			tmp_val.len = vec.pt.len;
+
+			parse_write_hex_str(&tmp_val);
+		} else
+			fprintf(info.fp_wr, "%s\n", NEG_TEST_STR);
+	}
+
+	return 0;
+}
+
+int
+parse_test_gcm_init(void)
+{
+	char *tmp;
+	uint32_t i;
+
+
+	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;
+			} else if (strstr(line, OP_DEC_STR)) {
+				info.op = FIPS_TEST_DEC_AUTH_VERIF;
+				info.callbacks = gcm_dec_vectors;
+			} else
+				return -EINVAL;
+		}
+	}
+
+	info.interim_callbacks = gcm_interim_vectors;
+	info.parse_writeback = parse_test_gcm_writeback;
+
+	return 0;
+}
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
index bb396e5..d45c88d 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
@@ -109,6 +109,11 @@ fips_test_parse_header(void)
 			ret = parse_test_aes_init();
 			if (ret < 0)
 				return ret;
+		} else if (strstr(info.vec[i], "GCM")) {
+			info.algo = FIPS_TEST_ALGO_AES_GCM;
+			ret = parse_test_gcm_init();
+			if (ret < 0)
+				return ret;
 		} else if (strstr(info.vec[i], "HMAC")) {
 			info.algo = FIPS_TEST_ALGO_HMAC;
 			ret = parse_test_hmac_init();
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
index c9b11dd..685bc0b 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
@@ -24,6 +24,7 @@
 
 enum fips_test_algorithms {
 		FIPS_TEST_ALGO_AES = 0,
+		FIPS_TEST_ALGO_AES_GCM,
 		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_MAX
@@ -172,6 +173,9 @@ int
 parse_test_hmac_init(void);
 
 int
+parse_test_gcm_init(void);
+
+int
 parser_read_uint8_hex(uint8_t *value, const char *p);
 
 int
diff --git a/examples/cryptodev_fips_validate/main.c b/examples/cryptodev_fips_validate/main.c
index 78add5a..e379c13 100644
--- a/examples/cryptodev_fips_validate/main.c
+++ b/examples/cryptodev_fips_validate/main.c
@@ -462,6 +462,70 @@ prepare_auth_op(void)
 }
 
 static int
+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);
+
+	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+	rte_pktmbuf_reset(env.mbuf);
+
+	memcpy(iv, vec.iv.val, vec.iv.len);
+
+	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 (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);
+
+		if (!pt) {
+			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
+					-ENOMEM);
+			return -ENOMEM;
+		}
+
+		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);
+	} 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;
+		}
+
+		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);
+	}
+
+	rte_crypto_op_attach_sym_session(env.op, env.sess);
+}
+
+static int
 prepare_aes_xform(struct rte_crypto_sym_xform *xform)
 {
 	const struct rte_cryptodev_symmetric_capability *cap;
@@ -578,6 +642,52 @@ prepare_hmac_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_gcm_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_aead_xform *aead_xform = &xform->aead;
+
+	xform->type = RTE_CRYPTO_SYM_XFORM_AEAD;
+
+	aead_xform->algo = RTE_CRYPTO_AEAD_AES_GCM;
+	aead_xform->aad_length = vec.aead.aad.len;
+	aead_xform->digest_length = vec.aead.digest.len;
+	aead_xform->iv.offset = IV_OFF;
+	aead_xform->iv.length = vec.iv.len;
+	aead_xform->key.data = vec.aead.key.val;
+	aead_xform->key.length = vec.aead.key.len;
+	aead_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_AEAD_OP_ENCRYPT :
+			RTE_CRYPTO_AEAD_OP_DECRYPT;
+
+	cap_idx.algo.aead = aead_xform->algo;
+	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
+
+	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_aead(cap,
+			aead_xform->key.length,
+			aead_xform->digest_length, aead_xform->aad_length,
+			aead_xform->iv.length) != 0) {
+		RTE_LOG(ERR, USER1,
+			"PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n",
+				info.device_name, aead_xform->key.length,
+				aead_xform->digest_length,
+				aead_xform->aad_length,
+				aead_xform->iv.length);
+		return -EPERM;
+	}
+
+	return 0;
+}
+
 static void
 get_writeback_data(struct fips_val *val)
 {
@@ -933,7 +1043,11 @@ init_test_ops(void)
 		else
 			test_ops.test = fips_generic_test;
 		break;
-
+	case FIPS_TEST_ALGO_AES_GCM:
+		test_ops.prepare_op = prepare_aead_op;
+		test_ops.prepare_xform = prepare_gcm_xform;
+		test_ops.test = fips_generic_test;
+		break;
 	default:
 		return -1;
 	}
diff --git a/examples/cryptodev_fips_validate/meson.build b/examples/cryptodev_fips_validate/meson.build
index a18e76d..510d2a7 100644
--- a/examples/cryptodev_fips_validate/meson.build
+++ b/examples/cryptodev_fips_validate/meson.build
@@ -12,6 +12,7 @@ sources = files(
 	'cryptodev_fips_parse_aes.c',
 	'cryptodev_fips_parse_hmac.c',
 	'cryptodev_fips_parse_3des.c',
+	'cryptodev_fips_parse_gcm.c',
 	'cryptodev_fips_parse_validate.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v4 6/8] examples: add cmac parser and enablement for test types
  2018-10-12 14:44 [dpdk-dev] [PATCH v4 0/8] FIPS validation capability Marko Kovacevic
                   ` (4 preceding siblings ...)
  2018-10-12 14:44 ` [dpdk-dev] [PATCH v4 5/8] examples: add gcm parser Marko Kovacevic
@ 2018-10-12 14:44 ` Marko Kovacevic
  2018-10-12 14:45 ` [dpdk-dev] [PATCH v4 7/8] examples: add ccm " Marko Kovacevic
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-12 14:44 UTC (permalink / raw)
  To: dev; +Cc: roy.fan.zhang, akhil.goyal, arkadiuszx.kusztal, Marko Kovacevic

Added enablement for CMAC parser, to allow the
application to parser the cmac request files and to validate all
test types supported.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
---
 examples/cryptodev_fips_validate/Makefile          |   1 +
 .../cryptodev_fips_parse_cmac.c                    | 116 +++++++++++++++++++++
 .../cryptodev_fips_parse_validate.c                |   5 +
 .../cryptodev_fips_validate.h                      |   4 +
 examples/cryptodev_fips_validate/main.c            |  43 ++++++++
 examples/cryptodev_fips_validate/meson.build       |   1 +
 6 files changed, 170 insertions(+)
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_cmac.c

diff --git a/examples/cryptodev_fips_validate/Makefile b/examples/cryptodev_fips_validate/Makefile
index 1eb0108..f5c2705 100644
--- a/examples/cryptodev_fips_validate/Makefile
+++ b/examples/cryptodev_fips_validate/Makefile
@@ -9,6 +9,7 @@ SRCS-y := cryptodev_fips_parse_aes.c
 SRCS-y += cryptodev_fips_parse_hmac.c
 SRCS-y += cryptodev_fips_parse_3des.c
 SRCS-y += cryptodev_fips_parse_gcm.c
+SRCS-y += cryptodev_fips_parse_cmac.c
 SRCS-y += cryptodev_fips_parse_validate.c
 SRCS-y += main.c
 
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_cmac.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_cmac.c
new file mode 100644
index 0000000..37c6317
--- /dev/null
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_cmac.c
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+#include <rte_string_fns.h>
+
+#include <rte_cryptodev.h>
+
+#include "cryptodev_fips_validate.h"
+
+#define NEW_LINE_STR	"#"
+#define OP_STR		"CMAC"
+
+#define ALGO_STR	"Alg = "
+#define MODE_STR	"Mode = "
+
+#define COUNT_STR	"Count = "
+#define KLEN_STR	"Klen = "
+#define PTLEN_STR	"Mlen = "
+#define TAGLEN_STR	"Tlen = "
+#define KEY_STR		"Key = "
+#define PT_STR		"Msg = "
+#define TAG_STR		"Mac = "
+
+#define GEN_STR		"Generate"
+#define VERIF_STR	"Verify"
+
+#define POS_NEG_STR	"Result = "
+#define PASS_STR	"P"
+#define FAIL_STR	"F"
+
+struct hash_algo_conversion {
+	const char *str;
+	enum fips_test_algorithms algo;
+} cmac_algo[] = {
+		{"AES", FIPS_TEST_ALGO_AES_CMAC},
+};
+
+static int
+parse_test_cmac_writeback(struct fips_val *val)
+{
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+		struct fips_val tmp_val = {val->val + vec.pt.len,
+				vec.cipher_auth.digest.len};
+
+		fprintf(info.fp_wr, "%s", TAG_STR);
+		parse_write_hex_str(&tmp_val);
+	} else {
+		fprintf(info.fp_wr, "%s", POS_NEG_STR);
+
+		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS)
+			fprintf(info.fp_wr, "%s\n", PASS_STR);
+		else if (vec.status == RTE_CRYPTO_OP_STATUS_AUTH_FAILED)
+			fprintf(info.fp_wr, "%s\n", FAIL_STR);
+		else
+			fprintf(info.fp_wr, "Error\n");
+	}
+
+	return 0;
+}
+
+struct fips_test_callback cmac_tests_vectors[] = {
+		{KLEN_STR, parser_read_uint32_val, &vec.cipher_auth.key},
+		{PTLEN_STR, parser_read_uint32_val, &vec.pt},
+		{TAGLEN_STR, parser_read_uint32_val, &vec.cipher_auth.digest},
+		{KEY_STR, parse_uint8_hex_str, &vec.cipher_auth.key},
+		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
+		{TAG_STR, parse_uint8_known_len_hex_str,
+				&vec.cipher_auth.digest},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+int
+parse_test_cmac_init(void)
+{
+	char *tmp;
+	uint32_t i, j;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		char *line = info.vec[i];
+
+		tmp = strstr(line, ALGO_STR);
+		if (!tmp)
+			continue;
+
+		for (j = 0; j < RTE_DIM(cmac_algo); j++) {
+			if (!strstr(line, cmac_algo[j].str))
+				continue;
+
+			info.algo = cmac_algo[j].algo;
+			break;
+		}
+
+		if (j == RTE_DIM(cmac_algo))
+			return -EINVAL;
+
+		tmp = strstr(line, MODE_STR);
+		if (!tmp)
+			return -1;
+
+		if (strstr(tmp, GEN_STR))
+			info.op = FIPS_TEST_ENC_AUTH_GEN;
+		else if (strstr(tmp, VERIF_STR))
+			info.op = FIPS_TEST_DEC_AUTH_VERIF;
+		else
+			return -EINVAL;
+	}
+
+	info.parse_writeback = parse_test_cmac_writeback;
+	info.callbacks = cmac_tests_vectors;
+
+	return 0;
+}
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
index d45c88d..4617c67 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
@@ -114,6 +114,11 @@ fips_test_parse_header(void)
 			ret = parse_test_gcm_init();
 			if (ret < 0)
 				return ret;
+		} else if (strstr(info.vec[i], "CMAC")) {
+			info.algo = FIPS_TEST_ALGO_AES_CMAC;
+			ret = parse_test_cmac_init();
+			if (ret < 0)
+				return 0;
 		} else if (strstr(info.vec[i], "HMAC")) {
 			info.algo = FIPS_TEST_ALGO_HMAC;
 			ret = parse_test_hmac_init();
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
index 685bc0b..7bd1e9a 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
@@ -25,6 +25,7 @@
 enum fips_test_algorithms {
 		FIPS_TEST_ALGO_AES = 0,
 		FIPS_TEST_ALGO_AES_GCM,
+		FIPS_TEST_ALGO_AES_CMAC,
 		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_MAX
@@ -176,6 +177,9 @@ int
 parse_test_gcm_init(void);
 
 int
+parse_test_cmac_init(void);
+
+int
 parser_read_uint8_hex(uint8_t *value, const char *p);
 
 int
diff --git a/examples/cryptodev_fips_validate/main.c b/examples/cryptodev_fips_validate/main.c
index e379c13..a5fa606 100644
--- a/examples/cryptodev_fips_validate/main.c
+++ b/examples/cryptodev_fips_validate/main.c
@@ -688,6 +688,44 @@ prepare_gcm_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_cmac_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_CMAC;
+	auth_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_AUTH_OP_GENERATE : RTE_CRYPTO_AUTH_OP_VERIFY;
+	auth_xform->digest_length = vec.cipher_auth.digest.len;
+	auth_xform->key.data = vec.cipher_auth.key.val;
+	auth_xform->key.length = vec.cipher_auth.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 void
 get_writeback_data(struct fips_val *val)
 {
@@ -1048,6 +1086,11 @@ init_test_ops(void)
 		test_ops.prepare_xform = prepare_gcm_xform;
 		test_ops.test = fips_generic_test;
 		break;
+	case FIPS_TEST_ALGO_AES_CMAC:
+		test_ops.prepare_op = prepare_auth_op;
+		test_ops.prepare_xform = prepare_cmac_xform;
+		test_ops.test = fips_generic_test;
+		break;
 	default:
 		return -1;
 	}
diff --git a/examples/cryptodev_fips_validate/meson.build b/examples/cryptodev_fips_validate/meson.build
index 510d2a7..4889d70 100644
--- a/examples/cryptodev_fips_validate/meson.build
+++ b/examples/cryptodev_fips_validate/meson.build
@@ -13,6 +13,7 @@ sources = files(
 	'cryptodev_fips_parse_hmac.c',
 	'cryptodev_fips_parse_3des.c',
 	'cryptodev_fips_parse_gcm.c',
+	'cryptodev_fips_parse_cmac.c',
 	'cryptodev_fips_parse_validate.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v4 7/8] examples: add ccm parser and enablement for test types
  2018-10-12 14:44 [dpdk-dev] [PATCH v4 0/8] FIPS validation capability Marko Kovacevic
                   ` (5 preceding siblings ...)
  2018-10-12 14:44 ` [dpdk-dev] [PATCH v4 6/8] examples: add cmac parser and enablement for test types Marko Kovacevic
@ 2018-10-12 14:45 ` Marko Kovacevic
  2018-10-12 14:45 ` [dpdk-dev] [PATCH v4 8/8] doc: add guides for fips validation Marko Kovacevic
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-12 14:45 UTC (permalink / raw)
  To: dev; +Cc: roy.fan.zhang, akhil.goyal, arkadiuszx.kusztal, Marko Kovacevic

Added enablement for CCM parser, to allow the
application to parser the ccm request files and to validate all
test types supported.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
---
 examples/cryptodev_fips_validate/Makefile          |   1 +
 .../cryptodev_fips_parse_ccm.c                     | 272 +++++++++++++++++++++
 .../cryptodev_fips_parse_validate.c                |   5 +
 .../cryptodev_fips_validate.h                      |  22 ++
 examples/cryptodev_fips_validate/main.c            |  56 ++++-
 examples/cryptodev_fips_validate/meson.build       |   1 +
 6 files changed, 356 insertions(+), 1 deletion(-)
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_ccm.c

diff --git a/examples/cryptodev_fips_validate/Makefile b/examples/cryptodev_fips_validate/Makefile
index f5c2705..4f1dc6b 100644
--- a/examples/cryptodev_fips_validate/Makefile
+++ b/examples/cryptodev_fips_validate/Makefile
@@ -10,6 +10,7 @@ SRCS-y += cryptodev_fips_parse_hmac.c
 SRCS-y += cryptodev_fips_parse_3des.c
 SRCS-y += cryptodev_fips_parse_gcm.c
 SRCS-y += cryptodev_fips_parse_cmac.c
+SRCS-y += cryptodev_fips_parse_ccm.c
 SRCS-y += cryptodev_fips_parse_validate.c
 SRCS-y += main.c
 
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_ccm.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_ccm.c
new file mode 100644
index 0000000..0fdb75a
--- /dev/null
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_ccm.c
@@ -0,0 +1,272 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <rte_string_fns.h>
+#include <rte_cryptodev.h>
+#include <rte_malloc.h>
+
+#include "cryptodev_fips_validate.h"
+
+#define DVPT_STR	"CCM-DVPT"
+#define VADT_STR	"CCM-VADT"
+#define VPT_STR		"CCM-VPT"
+#define VNT_STR		"CCM-VNT"
+#define VTT_STR		"CCM-VTT"
+
+#define PARAM_PREFIX	"["
+#define ALEN_PREFIX	"Alen = "
+#define PLEN_PREFIX	"Plen = "
+#define IVLEN_PREFIX	"Nlen = "
+#define DIGESTL_PREFIX	"Tlen = "
+
+#define COUNT_STR	"Count = "
+#define KEY_STR		"Key = "
+#define IV_STR		"Nonce = "
+#define PT_STR		"Payload = "
+#define CT_STR		"CT = "
+#define AAD_STR		"Adata = "
+#define POS_NEG_STR	"Result = "
+
+#define POS_KEYWORD	"Pass"
+#define NEG_KEYWORD	"Fail"
+
+static int
+parser_dvpt_interim(const char *key, char *src, struct fips_val *val)
+{
+	char *tmp, c, value[10];
+	char num_pattern[] = "0123456789";
+	int i = 0;
+
+	memset(value, 0, 10);
+
+	tmp = strstr(src, key);
+	if (!tmp)
+		return -1;
+
+	tmp += strlen(key);
+
+	c = tmp[0];
+
+	while (strchr(num_pattern, c) && i < 10) {
+		value[i++] = c;
+		c = tmp[i];
+	}
+
+	return parser_read_uint32_val("", value, val);
+}
+
+static int
+parse_dvpt_ct_hex_str(const char *key, char *src, struct fips_val *val)
+{
+	int ret;
+
+	val->len = vec.pt.len;
+
+	ret = parse_uint8_known_len_hex_str(key, src, val);
+	if (ret < 0)
+		return ret;
+
+	src += strlen(key) + val->len * 2;
+
+	ret = parse_uint8_known_len_hex_str("", src, &vec.aead.digest);
+	if (ret < 0) {
+		rte_free(val->val);
+		memset(val, 0, sizeof(*val));
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+parse_uint8_ccm_aad_str(const char *key, char *src, struct fips_val *val)
+{
+	uint32_t len = val->len, j;
+
+	src += strlen(key);
+
+	/* CCM aad requires 18 bytes padding before the real content */
+	val->val = rte_zmalloc(NULL, len + 18, 0);
+	if (!val->val)
+		return -1;
+
+	for (j = 0; j < len; j++) {
+		char byte[3] = {src[j * 2], src[j * 2 + 1], '\0'};
+
+		if (parser_read_uint8_hex(&val->val[j + 18], byte) < 0) {
+			rte_free(val->val);
+			memset(val, 0, sizeof(*val));
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+struct fips_test_callback ccm_vnt_vec[] = {
+		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
+		{AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad},
+		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vnt_interim_vec[] = {
+		{ALEN_PREFIX, parser_read_uint32_val, &vec.aead.aad},
+		{PLEN_PREFIX, parser_read_uint32_val, &vec.pt},
+		{DIGESTL_PREFIX, parser_read_uint32_val, &vec.aead.digest},
+		{IVLEN_PREFIX, parser_read_uint32_val, &vec.iv},
+		{KEY_STR, parse_uint8_hex_str, &vec.aead.key},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vtt_vec[] = {
+		{AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad},
+		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vtt_interim_vec[] = {
+		{ALEN_PREFIX, parser_read_uint32_val, &vec.aead.aad},
+		{PLEN_PREFIX, parser_read_uint32_val, &vec.pt},
+		{IVLEN_PREFIX, parser_read_uint32_val, &vec.iv},
+		{DIGESTL_PREFIX, parser_read_uint32_val, &vec.aead.digest},
+		{KEY_STR, parse_uint8_hex_str, &vec.aead.key},
+		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vadt_vec[] = {
+		{AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad},
+		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vadt_interim_vec[] = {
+		{PLEN_PREFIX, parser_read_uint32_val, &vec.pt},
+		{IVLEN_PREFIX, parser_read_uint32_val, &vec.iv},
+		{ALEN_PREFIX, parser_read_uint32_val, &vec.aead.aad},
+		{DIGESTL_PREFIX, parser_read_uint32_val, &vec.aead.digest},
+		{KEY_STR, parse_uint8_hex_str, &vec.aead.key},
+		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vpt_vec[] = {
+		{AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad},
+		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vpt_interim_vec[] = {
+		{ALEN_PREFIX, parser_read_uint32_val, &vec.aead.aad},
+		{IVLEN_PREFIX, parser_read_uint32_val, &vec.iv},
+		{DIGESTL_PREFIX, parser_read_uint32_val, &vec.aead.digest},
+		{PLEN_PREFIX, parser_read_uint32_val, &vec.pt},
+		{KEY_STR, parse_uint8_hex_str, &vec.aead.key},
+		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_dvpt_vec[] = {
+		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
+		{AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad},
+		{CT_STR, parse_dvpt_ct_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_dvpt_interim_vec[] = {
+		{ALEN_PREFIX, parser_dvpt_interim, &vec.aead.aad},
+		{PLEN_PREFIX, parser_dvpt_interim, &vec.pt},
+		{IVLEN_PREFIX, parser_dvpt_interim, &vec.iv},
+		{DIGESTL_PREFIX, parser_dvpt_interim, &vec.aead.digest},
+		{KEY_STR, parse_uint8_hex_str, &vec.aead.key},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct ccm_test_types {
+	const char *str;
+	uint32_t type;
+	const struct fips_test_callback *cb;
+	const struct fips_test_callback *cb_interim;
+	enum fips_test_op op;
+} ctt[] = {
+		{DVPT_STR, CCM_DVPT, ccm_dvpt_vec, ccm_dvpt_interim_vec,
+			FIPS_TEST_DEC_AUTH_VERIF},
+		{VPT_STR, CCM_VPT, ccm_vpt_vec, ccm_vpt_interim_vec,
+			FIPS_TEST_ENC_AUTH_GEN},
+		{VADT_STR, CCM_VADT, ccm_vadt_vec, ccm_vadt_interim_vec,
+			FIPS_TEST_ENC_AUTH_GEN},
+		{VNT_STR, CCM_VNT, ccm_vnt_vec, ccm_vnt_interim_vec,
+			FIPS_TEST_ENC_AUTH_GEN},
+		{VTT_STR, CCM_VTT, ccm_vtt_vec, ccm_vtt_interim_vec,
+			FIPS_TEST_ENC_AUTH_GEN},
+};
+
+static int
+parse_test_ccm_writeback(struct fips_val *val)
+{
+	struct fips_val tmp_val;
+
+	switch (info.interim_info.ccm_data.test_type) {
+	case CCM_DVPT:
+		fprintf(info.fp_wr, "%s", POS_NEG_STR);
+		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS) {
+			fprintf(info.fp_wr, "%s\n", POS_KEYWORD);
+			fprintf(info.fp_wr, "%s", PT_STR);
+
+			tmp_val.val = val->val;
+			tmp_val.len = vec.pt.len;
+
+			if (tmp_val.len == 0)
+				fprintf(info.fp_wr, "00\n");
+			else
+				parse_write_hex_str(&tmp_val);
+		} else
+			fprintf(info.fp_wr, "%s\n", NEG_KEYWORD);
+
+		break;
+
+	case CCM_VADT:
+	case CCM_VNT:
+	case CCM_VPT:
+	case CCM_VTT:
+		fprintf(info.fp_wr, "%s", CT_STR);
+
+		parse_write_hex_str(val);
+
+		break;
+
+	}
+
+	return 0;
+}
+
+int
+parse_test_ccm_init(void)
+{
+
+	uint32_t i;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		char *line = info.vec[i];
+		uint32_t j;
+
+		for (j = 0; j < RTE_DIM(ctt); j++)
+			if (strstr(line, ctt[j].str)) {
+				info.interim_info.ccm_data.test_type =
+						ctt[j].type;
+				info.callbacks = ctt[j].cb;
+				info.interim_callbacks = ctt[j].cb_interim;
+				info.op = ctt[j].op;
+				break;
+		}
+	}
+
+	info.parse_writeback = parse_test_ccm_writeback;
+
+	return 0;
+}
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
index 4617c67..47e3732 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
@@ -119,6 +119,11 @@ fips_test_parse_header(void)
 			ret = parse_test_cmac_init();
 			if (ret < 0)
 				return 0;
+		} else if (strstr(info.vec[i], "CCM")) {
+			info.algo = FIPS_TEST_ALGO_AES_CCM;
+			ret = parse_test_ccm_init();
+			if (ret < 0)
+				return 0;
 		} else if (strstr(info.vec[i], "HMAC")) {
 			info.algo = FIPS_TEST_ALGO_HMAC;
 			ret = parse_test_hmac_init();
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
index 7bd1e9a..afa0c0a 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
@@ -26,6 +26,7 @@ enum fips_test_algorithms {
 		FIPS_TEST_ALGO_AES = 0,
 		FIPS_TEST_ALGO_AES_GCM,
 		FIPS_TEST_ALGO_AES_CMAC,
+		FIPS_TEST_ALGO_AES_CCM,
 		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_MAX
@@ -102,6 +103,14 @@ enum fips_tdes_test_types {
 	TDES_MMT /* Multi block Message Test */
 };
 
+enum fips_ccm_test_types {
+	CCM_VADT	= 1, /* Variable Associated Data Test */
+	CCM_VPT,		 /* Variable Payload Test */
+	CCM_VNT,		 /* Variable Nonce Test */
+	CCM_VTT,		 /* Variable Tag Test */
+	CCM_DVPT,	 /*  Decryption-Verification Process Test */
+};
+
 struct aesavs_interim_data {
 	enum fips_aesavs_test_types test_type;
 	uint32_t cipher_algo;
@@ -117,6 +126,15 @@ struct tdes_interim_data {
 	uint32_t nb_keys;
 };
 
+struct ccm_interim_data {
+	enum fips_ccm_test_types test_type;
+	uint32_t aad_len;
+	uint32_t pt_len;
+	uint32_t digest_len;
+	uint32_t key_len;
+	uint32_t iv_len;
+};
+
 struct fips_test_interim_info {
 	FILE *fp_rd;
 	FILE *fp_wr;
@@ -132,6 +150,7 @@ struct fips_test_interim_info {
 		struct aesavs_interim_data aes_data;
 		struct hmac_interim_data hmac_data;
 		struct tdes_interim_data tdes_data;
+		struct ccm_interim_data ccm_data;
 
 	} interim_info;
 
@@ -180,6 +199,9 @@ int
 parse_test_cmac_init(void);
 
 int
+parse_test_ccm_init(void);
+
+int
 parser_read_uint8_hex(uint8_t *value, const char *p);
 
 int
diff --git a/examples/cryptodev_fips_validate/main.c b/examples/cryptodev_fips_validate/main.c
index a5fa606..5f15cb9 100644
--- a/examples/cryptodev_fips_validate/main.c
+++ b/examples/cryptodev_fips_validate/main.c
@@ -470,7 +470,10 @@ prepare_aead_op(void)
 	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
 	rte_pktmbuf_reset(env.mbuf);
 
-	memcpy(iv, vec.iv.val, vec.iv.len);
+	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);
 
 	sym->m_src = env.mbuf;
 	sym->aead.data.offset = 0;
@@ -726,6 +729,52 @@ prepare_cmac_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_ccm_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_aead_xform *aead_xform = &xform->aead;
+
+	xform->type = RTE_CRYPTO_SYM_XFORM_AEAD;
+
+	aead_xform->algo = RTE_CRYPTO_AEAD_AES_CCM;
+	aead_xform->aad_length = vec.aead.aad.len;
+	aead_xform->digest_length = vec.aead.digest.len;
+	aead_xform->iv.offset = IV_OFF;
+	aead_xform->iv.length = vec.iv.len;
+	aead_xform->key.data = vec.aead.key.val;
+	aead_xform->key.length = vec.aead.key.len;
+	aead_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_AEAD_OP_ENCRYPT :
+			RTE_CRYPTO_AEAD_OP_DECRYPT;
+
+	cap_idx.algo.aead = aead_xform->algo;
+	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
+
+	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_aead(cap,
+			aead_xform->key.length,
+			aead_xform->digest_length, aead_xform->aad_length,
+			aead_xform->iv.length) != 0) {
+		RTE_LOG(ERR, USER1,
+			"PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n",
+				info.device_name, aead_xform->key.length,
+				aead_xform->digest_length,
+				aead_xform->aad_length,
+				aead_xform->iv.length);
+		return -EPERM;
+	}
+
+	return 0;
+}
+
 static void
 get_writeback_data(struct fips_val *val)
 {
@@ -1091,6 +1140,11 @@ init_test_ops(void)
 		test_ops.prepare_xform = prepare_cmac_xform;
 		test_ops.test = fips_generic_test;
 		break;
+	case FIPS_TEST_ALGO_AES_CCM:
+		test_ops.prepare_op = prepare_aead_op;
+		test_ops.prepare_xform = prepare_ccm_xform;
+		test_ops.test = fips_generic_test;
+		break;
 	default:
 		return -1;
 	}
diff --git a/examples/cryptodev_fips_validate/meson.build b/examples/cryptodev_fips_validate/meson.build
index 4889d70..e3bf7ac 100644
--- a/examples/cryptodev_fips_validate/meson.build
+++ b/examples/cryptodev_fips_validate/meson.build
@@ -14,6 +14,7 @@ sources = files(
 	'cryptodev_fips_parse_3des.c',
 	'cryptodev_fips_parse_gcm.c',
 	'cryptodev_fips_parse_cmac.c',
+	'cryptodev_fips_parse_ccm.c',
 	'cryptodev_fips_parse_validate.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v4 8/8] doc: add guides for fips validation
  2018-10-12 14:44 [dpdk-dev] [PATCH v4 0/8] FIPS validation capability Marko Kovacevic
                   ` (6 preceding siblings ...)
  2018-10-12 14:45 ` [dpdk-dev] [PATCH v4 7/8] examples: add ccm " Marko Kovacevic
@ 2018-10-12 14:45 ` Marko Kovacevic
  2018-10-15  6:36 ` [dpdk-dev] [PATCH v4 0/8] FIPS validation capability Kusztal, ArkadiuszX
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-12 14:45 UTC (permalink / raw)
  To: dev; +Cc: roy.fan.zhang, akhil.goyal, arkadiuszx.kusztal, Marko Kovacevic

Document explains how to run the fips sample app
and instructions users need to parser all the request
files and generate the response files.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
---
 doc/guides/rel_notes/release_18_11.rst       |   6 ++
 doc/guides/sample_app_ug/fips_validation.rst | 105 +++++++++++++++++++++++++++
 doc/guides/sample_app_ug/index.rst           |   1 +
 3 files changed, 112 insertions(+)
 create mode 100644 doc/guides/sample_app_ug/fips_validation.rst

diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index 436b20e..83ad92e 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -54,6 +54,12 @@ New Features
      Also, make sure to start the actual text at the margin.
      =========================================================
 
+* **Added Cryptodev Fips Validation Example Application.**
+
+  Added an example application to parse and perform symmetric cryptography
+  computation to the NIST Cryptographic Algorithm Validation Program (CAVP)
+  test vectors.
+
 * **Added support for using externally allocated memory in DPDK.**
 
   DPDK has gained support for creating new ``rte_malloc`` heaps referencing
diff --git a/doc/guides/sample_app_ug/fips_validation.rst b/doc/guides/sample_app_ug/fips_validation.rst
new file mode 100644
index 0000000..e67b513
--- /dev/null
+++ b/doc/guides/sample_app_ug/fips_validation.rst
@@ -0,0 +1,105 @@
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(c) 2018 Intel Corporation.
+
+Federal Information Processing Standards (FIPS) CryptoDev Validation
+====================================================================
+
+Overview
+--------
+
+Federal Information Processing Standards (FIPS) are publicly announced standards
+developed by the United States federal government for use in computer systems by
+non-military government agencies and government contractors.
+
+This application is used to parse and perform symmetric cryptography
+computation to the NIST Cryptographic Algorithm Validation Program (CAVP) test
+vectors.
+
+Limitations
+-----------
+
+* Only NIST CAVP request files are parsed by this application.
+* The version of request file supported is ``CAVS 21.0``
+* If the header comment in a ``.req`` file does not contain a Algo tag
+  i.e ``AES,TDES,GCM`` you need to manually add it into the head comment for
+  example::
+
+      # VARIABLE KEY - KAT for CBC / # TDES VARIABLE KEY - KAT for CBC
+
+* The application does not supply the test vectors. The user is expected to
+  obtain the test vector files from `NIST
+  <https://csrc.nist.gov/projects/cryptographic-algorithm-validation-
+  program/block-ciphers>`_
+* Supported test vectors
+    * AES-CBC (128,192,256) - GFSbox, KeySbox, MCT, MMT
+    * AES-GCM (128,192,256) - EncryptExtIV, Decrypt
+    * AES-CCM (128) - VADT, VNT, VPT, VTT, DVPT
+    * AES-CMAC (128) - Generate, Verify
+    * HMAC (SHA1, SHA224, SHA256, SHA384, SHA512)
+    * TDES-CBC (1 Key, 2 Keys, 3 Keys) - MMT, Monte, Permop, Subkey, Varkey,
+      VarText
+
+Compiling the Application
+-------------------------
+
+* Compile Application
+
+    .. code-block:: console
+
+         make -C examples/cryptodev_fips_validate
+
+*  Run ``dos2unix`` on the request files
+
+    .. code-block:: console
+
+         dos2unix AES/req/*
+         dos2unix AES_GCM/req/*
+         dos2unix CCM/req/*
+         dos2unix CMAC/req/*
+         dos2unix HMAC/req/*
+         dos2unix TDES/req/*
+
+Running the Application
+-----------------------
+
+The application requires a number of command line options:
+
+    .. code-block:: console
+
+         ./cryptodev_fips_validate_app [EAL options]
+         -- --req-file FILE_PATH/FOLDER_PATH
+         --rsp-file FILE_PATH/FOLDER_PATH
+         [--cryptodev DEVICE_NAME] [--cryptodev-id ID] [--path-is-folder]
+
+where,
+  * req-file: The path of the request file or folder, separated by
+    ``path-is-folder`` option.
+
+  * rsp-file: The path that the response file or folder is stored. separated by
+    ``path-is-folder`` option.
+
+  * cryptodev: The name of the target DPDK Crypto device to be validated.
+
+  * cryptodev-id: The id of the target DPDK Crypto device to be validated.
+
+  * path-is-folder: If presented the application expects req-file and rsp-file
+    are folder paths.
+
+To run the application in linuxapp environment to test one AES FIPS test data
+file for crypto_aesni_mb PMD, issue the command:
+
+.. code-block:: console
+
+    $ ./cryptodev_fips_validate_app --vdev crypto_aesni_mb --
+    --req-file /PATH/TO/REQUEST/FILE.req --rsp-file ./PATH/TO/RESPONSE/FILE.rsp
+    --cryptodev crypto_aesni_mb
+
+To run the application in linuxapp environment to test all AES-GCM FIPS test
+data files in one folder for crypto_aesni_gcm PMD, issue the command:
+
+.. code-block:: console
+
+    $ ./cryptodev_fips_validate_app --vdev crypto_aesni_gcm0 --
+    --req-file /PATH/TO/REQUEST/FILE/FOLDER/
+    --rsp-file ./PATH/TO/RESPONSE/FILE/FOLDER/
+    --cryptodev-id 0 --path-is-folder
diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst
index 74b12af..65c12d9 100644
--- a/doc/guides/sample_app_ug/index.rst
+++ b/doc/guides/sample_app_ug/index.rst
@@ -57,6 +57,7 @@ Sample Applications User Guides
     performance_thread
     ipsec_secgw
     bbdev_app
+    fips_validation
 
 **Figures**
 
-- 
2.9.5

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

* Re: [dpdk-dev] [PATCH v4 0/8] FIPS validation capability
  2018-10-12 14:44 [dpdk-dev] [PATCH v4 0/8] FIPS validation capability Marko Kovacevic
                   ` (7 preceding siblings ...)
  2018-10-12 14:45 ` [dpdk-dev] [PATCH v4 8/8] doc: add guides for fips validation Marko Kovacevic
@ 2018-10-15  6:36 ` Kusztal, ArkadiuszX
  2018-10-16 14:40 ` Akhil Goyal
  2018-10-17 12:49 ` [dpdk-dev] [PATCH v5 " Marko Kovacevic
  10 siblings, 0 replies; 52+ messages in thread
From: Kusztal, ArkadiuszX @ 2018-10-15  6:36 UTC (permalink / raw)
  To: Kovacevic, Marko, dev; +Cc: Zhang, Roy Fan, akhil.goyal



> -----Original Message-----
> From: Kovacevic, Marko
> Sent: Friday, October 12, 2018 4:45 PM
> To: dev@dpdk.org
> Cc: Zhang, Roy Fan <roy.fan.zhang@intel.com>; akhil.goyal@nxp.com;
> Kusztal, ArkadiuszX <arkadiuszx.kusztal@intel.com>; Kovacevic, Marko
> <marko.kovacevic@intel.com>
> Subject: [PATCH v4 0/8] FIPS validation capability
> 
> This sample application is made for the purpose so that users of DPDK who
> wish to get FIPS certification for their platforms, this sample app enables
> users to parse test vectors that is gotten from NIST and be able to get a
> generated response file which they can then verify and be sure their system
> will pass FIPS certification.
> 
> Marko Kovacevic (8):
> v4:
> - Added Limitation
> - Changed TDES BLOCK SIZE from 16 -> 8
>   as DES block size is 64bits (main.c)
> v3:
> - Fixed a no-testing bug
> - Fixed some code style issue
> 
> v2:
> - Refactor the code.
> - Move the code from test to sample applcation
> 
>   examples: add fips validation into examples
>   examples: add aes parser and enablement for test types
>   examples: add hmac parser
>   examples: add TDES parser and enablement for test types
>   examples: add gcm parser
>   examples: add cmac parser and enablement for test types
>   examples: add ccm parser and enablement for test types
>   doc: add guides for fips validation
> 
>  doc/guides/rel_notes/release_18_11.rst             |    6 +
>  doc/guides/sample_app_ug/fips_validation.rst       |  105 ++
>  doc/guides/sample_app_ug/index.rst                 |    1 +
>  examples/cryptodev_fips_validate/Makefile          |   75 ++
>  .../cryptodev_fips_parse_3des.c                    |  259 +++++
>  .../cryptodev_fips_parse_aes.c                     |  188 +++
>  .../cryptodev_fips_parse_ccm.c                     |  272 +++++
>  .../cryptodev_fips_parse_cmac.c                    |  116 ++
>  .../cryptodev_fips_parse_gcm.c                     |  125 ++
>  .../cryptodev_fips_parse_hmac.c                    |  105 ++
>  .../cryptodev_fips_parse_validate.c                |  593 ++++++++++
>  .../cryptodev_fips_validate.h                      |  234 ++++
>  examples/cryptodev_fips_validate/main.c            | 1221
> ++++++++++++++++++++
>  examples/cryptodev_fips_validate/meson.build       |   20 +
>  14 files changed, 3320 insertions(+)
>  create mode 100644 doc/guides/sample_app_ug/fips_validation.rst
>  create mode 100644 examples/cryptodev_fips_validate/Makefile
>  create mode 100644
> examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c
>  create mode 100644
> examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c
>  create mode 100644
> examples/cryptodev_fips_validate/cryptodev_fips_parse_ccm.c
>  create mode 100644
> examples/cryptodev_fips_validate/cryptodev_fips_parse_cmac.c
>  create mode 100644
> examples/cryptodev_fips_validate/cryptodev_fips_parse_gcm.c
>  create mode 100644
> examples/cryptodev_fips_validate/cryptodev_fips_parse_hmac.c
>  create mode 100644
> examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
>  create mode 100644
> examples/cryptodev_fips_validate/cryptodev_fips_validate.h
>  create mode 100644 examples/cryptodev_fips_validate/main.c
>  create mode 100644 examples/cryptodev_fips_validate/meson.build
> 
> --
> 2.9.5

Series-acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>

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

* Re: [dpdk-dev] [PATCH v4 0/8] FIPS validation capability
  2018-10-12 14:44 [dpdk-dev] [PATCH v4 0/8] FIPS validation capability Marko Kovacevic
                   ` (8 preceding siblings ...)
  2018-10-15  6:36 ` [dpdk-dev] [PATCH v4 0/8] FIPS validation capability Kusztal, ArkadiuszX
@ 2018-10-16 14:40 ` Akhil Goyal
  2018-10-17 12:49 ` [dpdk-dev] [PATCH v5 " Marko Kovacevic
  10 siblings, 0 replies; 52+ messages in thread
From: Akhil Goyal @ 2018-10-16 14:40 UTC (permalink / raw)
  To: Marko Kovacevic, dev; +Cc: roy.fan.zhang, arkadiuszx.kusztal

Hi Marko/Fan,

On 10/12/2018 8:14 PM, Marko Kovacevic wrote:
> This sample application is made for the purpose so that users of DPDK
> who wish to get FIPS certification for their platforms, this sample app enables
> users to parse test vectors that is gotten from NIST and be able to get
> a generated response file which they can then verify and be sure their
> system will pass FIPS certification.
>
> Marko Kovacevic (8):
> v4:
> - Added Limitation
> - Changed TDES BLOCK SIZE from 16 -> 8
>    as DES block size is 64bits (main.c)
> v3:
> - Fixed a no-testing bug
> - Fixed some code style issue
>
> v2:
> - Refactor the code.
> - Move the code from test to sample applcation
>
>    examples: add fips validation into examples
>    examples: add aes parser and enablement for test types
>    examples: add hmac parser
>    examples: add TDES parser and enablement for test types
>    examples: add gcm parser
>    examples: add cmac parser and enablement for test types
>    examples: add ccm parser and enablement for test types
>    doc: add guides for fips validation
>
>   doc/guides/rel_notes/release_18_11.rst             |    6 +
>   doc/guides/sample_app_ug/fips_validation.rst       |  105 ++
>   doc/guides/sample_app_ug/index.rst                 |    1 +
>   examples/cryptodev_fips_validate/Makefile          |   75 ++
>   .../cryptodev_fips_parse_3des.c                    |  259 +++++
>   .../cryptodev_fips_parse_aes.c                     |  188 +++
>   .../cryptodev_fips_parse_ccm.c                     |  272 +++++
>   .../cryptodev_fips_parse_cmac.c                    |  116 ++
>   .../cryptodev_fips_parse_gcm.c                     |  125 ++
>   .../cryptodev_fips_parse_hmac.c                    |  105 ++
>   .../cryptodev_fips_parse_validate.c                |  593 ++++++++++
>   .../cryptodev_fips_validate.h                      |  234 ++++
>   examples/cryptodev_fips_validate/main.c            | 1221 ++++++++++++++++++++
>   examples/cryptodev_fips_validate/meson.build       |   20 +
>   14 files changed, 3320 insertions(+)
>   create mode 100644 doc/guides/sample_app_ug/fips_validation.rst
>   create mode 100644 examples/cryptodev_fips_validate/Makefile
>   create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c
>   create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c
>   create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_ccm.c
>   create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_cmac.c
>   create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_gcm.c
>   create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_hmac.c
>   create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
>   create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_validate.h
>   create mode 100644 examples/cryptodev_fips_validate/main.c
>   create mode 100644 examples/cryptodev_fips_validate/meson.build
>
Some generic comments
- patch titles should be examples/cryptodev_fips_validate:XXX
- app name could be fips_validation. better to have same name file in doc.
- MAINTAINERS file is not updated.
- better to mention about Publication 140-2 of FIPS (which represent the 
crypto cases) in documentation
- Please mention in the documentation and the application as well that 
the .req file is optional and the application can be run without that. 
and the procedure to get the .req file as the documentation depicts that 
the .req file is present in the link provided.
- Why is the build dependent on bus_pci? Does it have limitation for not 
being used by any other buses? I think this should be bus independent.

Thanks,
Akhil


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

* [dpdk-dev] [PATCH v5 0/8] FIPS validation capability
  2018-10-12 14:44 [dpdk-dev] [PATCH v4 0/8] FIPS validation capability Marko Kovacevic
                   ` (9 preceding siblings ...)
  2018-10-16 14:40 ` Akhil Goyal
@ 2018-10-17 12:49 ` Marko Kovacevic
  2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 1/8] examples/cryptodev_fips_validate: add fips validation into examples Marko Kovacevic
                     ` (9 more replies)
  10 siblings, 10 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-17 12:49 UTC (permalink / raw)
  To: dev; +Cc: roy.fan.zhang, akhil.goyal, arkadiuszx.kusztal, Marko Kovacevic

This sample application is made for the purpose so that users of DPDK
who wish to get FIPS certification for their platforms, this sample app enables
users to parse test vectors that is gotten from NIST and be able to get
a generated response file which they can then verify and be sure their
system will pass FIPS certification.


Marko Kovacevic (8):
v5:
  - Changed patch titles
  - Added MAINTAINERS File
  - Removed bus_pci Dependency
  - Updated documentation
  - Changed app name
v4:
- Added Limitation
- Changed TDES BLOCK SIZE from 16 -> 8
  as DES block size is 64bits (main.c)
v3:
- Fixed a no-testing bug
- Fixed some code style issue

v2:
- Refactor the code.
- Move the code from test to sample applcation

  examples/cryptodev_fips_validate: add fips validation into examples
  examples/cryptodev_fips_validate: add aes parser and enablement for
    test types
  examples/cryptodev_fips_validate: add hmac parser
  examples/cryptodev_fips_validate: add TDES parser and enablement for
    test types
  examples/cryptodev_fips_validate: add gcm parser
  examples/cryptodev_fips_validate: add cmac parser and enablement for
    test types
  examples/cryptodev_fips_validate: add ccm parser and enablement for
    test types
  doc/guides/sample_app_ug: add guides for fips validation

 MAINTAINERS                                        |    4 +
 doc/guides/rel_notes/release_18_11.rst             |    6 +
 doc/guides/sample_app_ug/fips_validation.rst       |  119 ++
 doc/guides/sample_app_ug/index.rst                 |    1 +
 examples/cryptodev_fips_validate/Makefile          |   75 ++
 .../cryptodev_fips_parse_3des.c                    |  259 +++++
 .../cryptodev_fips_parse_aes.c                     |  188 +++
 .../cryptodev_fips_parse_ccm.c                     |  272 +++++
 .../cryptodev_fips_parse_cmac.c                    |  116 ++
 .../cryptodev_fips_parse_gcm.c                     |  125 ++
 .../cryptodev_fips_parse_hmac.c                    |  105 ++
 .../cryptodev_fips_parse_validate.c                |  593 ++++++++++
 .../cryptodev_fips_validate.h                      |  234 ++++
 examples/cryptodev_fips_validate/main.c            | 1221 ++++++++++++++++++++
 examples/cryptodev_fips_validate/meson.build       |   20 +
 15 files changed, 3338 insertions(+)
 create mode 100644 doc/guides/sample_app_ug/fips_validation.rst
 create mode 100644 examples/cryptodev_fips_validate/Makefile
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_ccm.c
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_cmac.c
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_gcm.c
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_hmac.c
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_validate.h
 create mode 100644 examples/cryptodev_fips_validate/main.c
 create mode 100644 examples/cryptodev_fips_validate/meson.build

-- 
2.9.5

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

* [dpdk-dev] [PATCH v5 1/8] examples/cryptodev_fips_validate: add fips validation into examples
  2018-10-17 12:49 ` [dpdk-dev] [PATCH v5 " Marko Kovacevic
@ 2018-10-17 12:49   ` Marko Kovacevic
  2018-10-24 12:13     ` Akhil Goyal
  2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 2/8] examples/cryptodev_fips_validate: add aes parser and enablement for test types Marko Kovacevic
                     ` (8 subsequent siblings)
  9 siblings, 1 reply; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-17 12:49 UTC (permalink / raw)
  To: dev; +Cc: roy.fan.zhang, akhil.goyal, arkadiuszx.kusztal, Marko Kovacevic

Added FIPS application into the examples to allow
users to use a simple sample app to validate
their systems and be able to get FIPS certification.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 examples/cryptodev_fips_validate/Makefile          |  69 +++
 .../cryptodev_fips_parse_validate.c                | 562 +++++++++++++++++++++
 .../cryptodev_fips_validate.h                      | 150 ++++++
 examples/cryptodev_fips_validate/main.c            | 388 ++++++++++++++
 examples/cryptodev_fips_validate/meson.build       |  14 +
 5 files changed, 1183 insertions(+)
 create mode 100644 examples/cryptodev_fips_validate/Makefile
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_validate.h
 create mode 100644 examples/cryptodev_fips_validate/main.c
 create mode 100644 examples/cryptodev_fips_validate/meson.build

diff --git a/examples/cryptodev_fips_validate/Makefile b/examples/cryptodev_fips_validate/Makefile
new file mode 100644
index 0000000..7f0e603
--- /dev/null
+++ b/examples/cryptodev_fips_validate/Makefile
@@ -0,0 +1,69 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2010-2014 Intel Corporation
+
+# binary name
+APP = fips_validation
+
+# all source are stored in SRCS-y
+SRCS-y += cryptodev_fips_parse_validate.c
+SRCS-y += main.c
+
+# Build using pkg-config variables if possible
+$(shell pkg-config --exists libdpdk)
+ifeq ($(.SHELLSTATUS),0)
+
+all: shared
+.PHONY: shared static
+shared: build/$(APP)-shared
+	ln -sf $(APP)-shared build/$(APP)
+static: build/$(APP)-static
+	ln -sf $(APP)-static build/$(APP)
+
+PC_FILE := $(shell pkg-config --path libdpdk)
+CFLAGS += -O3 $(shell pkg-config --cflags libdpdk)
+LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk)
+LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk)
+
+build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
+	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
+
+build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build
+	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC)
+
+build:
+	@mkdir -p $@
+
+.PHONY: clean
+clean:
+	rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared
+	rmdir --ignore-fail-on-non-empty build
+
+else
+
+ifeq ($(RTE_SDK),)
+$(error "Please define RTE_SDK environment variable")
+endif
+
+# Default target, can be overridden by command line or environment
+RTE_TARGET ?= x86_64-native-linuxapp-gcc
+
+INC += $(sort $(wildcard *.h))
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+CFLAGS += $(WERROR_FLAGS)
+
+# workaround for a gcc bug with noreturn attribute
+# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603
+ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
+CFLAGS_main.o += -Wno-return-type
+endif
+
+CFLAGS += -DALLOW_EXPERIMENTAL_API
+CFLAGS += -I$(SRCDIR)
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+include $(RTE_SDK)/mk/rte.extapp.mk
+
+endif
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
new file mode 100644
index 0000000..aec5bb9
--- /dev/null
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
@@ -0,0 +1,562 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <rte_string_fns.h>
+#include <rte_cryptodev.h>
+#include <rte_malloc.h>
+
+#include "cryptodev_fips_validate.h"
+
+#define skip_white_spaces(pos)			\
+({						\
+	__typeof__(pos) _p = (pos);		\
+	for ( ; isspace(*_p); _p++)		\
+		;				\
+	_p;					\
+})
+
+static int
+get_file_line(void)
+{
+	FILE *fp = info.fp_rd;
+	char *line = info.one_line_text;
+	char c;
+	uint32_t loc = 0;
+
+	memset(line, 0, MAX_LINE_CHAR);
+	while ((c = fgetc(fp)) != EOF) {
+		if (loc >= MAX_LINE_CHAR - 1)
+			return -ENOMEM;
+		if (c == '\n')
+			return 0;
+		line[loc++] = c;
+	}
+
+	if (c == EOF)
+		return -EOF;
+
+	return 0;
+}
+
+int
+fips_test_fetch_one_block(void)
+{
+	size_t size;
+	int ret = 0;
+	uint32_t i;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		free(info.vec[i]);
+		info.vec[i] = NULL;
+	}
+
+	i = 0;
+	do {
+		if (i >= MAX_LINE_PER_VECTOR) {
+			ret = -ENOMEM;
+			goto error_exit;
+		}
+
+		ret = get_file_line();
+		size = strlen(info.one_line_text);
+		if (size == 0)
+			break;
+
+		info.vec[i] = calloc(1, size + 5);
+		if (info.vec[i] == NULL)
+			goto error_exit;
+
+		strlcpy(info.vec[i], info.one_line_text, size + 1);
+		i++;
+	} while (ret == 0);
+
+	info.nb_vec_lines = i;
+
+	return ret;
+
+error_exit:
+	for (i = 0; i < MAX_LINE_PER_VECTOR; i++)
+		if (info.vec[i] != NULL) {
+			free(info.vec[i]);
+			info.vec[i] = NULL;
+		}
+
+	info.nb_vec_lines = 0;
+
+	return -ENOMEM;
+}
+
+static int
+fips_test_parse_header(void)
+{
+	uint32_t i;
+	char *tmp;
+	int ret;
+	time_t t = time(NULL);
+	struct tm *tm_now = localtime(&t);
+
+	ret = fips_test_fetch_one_block();
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+
+		tmp = strstr(info.vec[i], "# Config info for ");
+		if (tmp != NULL) {
+			fprintf(info.fp_wr, "%s%s\n", "# Config info for DPDK Cryptodev ",
+					info.device_name);
+			continue;
+		}
+
+		tmp = strstr(info.vec[i], "#  HMAC information for ");
+		if (tmp != NULL) {
+			fprintf(info.fp_wr, "%s%s\n", "#  HMAC information for "
+				"DPDK Cryptodev ",
+				info.device_name);
+			continue;
+		}
+
+		tmp = strstr(info.vec[i], "# Config Info for : ");
+		if (tmp != NULL) {
+
+			fprintf(info.fp_wr, "%s%s\n", "# Config Info for DPDK Cryptodev : ",
+					info.device_name);
+			continue;
+		}
+
+		tmp = strstr(info.vec[i], "# information for ");
+		if (tmp != NULL) {
+
+			char tmp_output[128] = {0};
+
+			strlcpy(tmp_output, info.vec[i], tmp - info.vec[i] + 1);
+
+			fprintf(info.fp_wr, "%s%s%s\n", tmp_output,
+					"information for DPDK Cryptodev ",
+					info.device_name);
+			continue;
+		}
+
+		tmp = strstr(info.vec[i], " test information for ");
+		if (tmp != NULL) {
+			char tmp_output[128] = {0};
+
+			strlcpy(tmp_output, info.vec[i], tmp - info.vec[i] + 1);
+
+			fprintf(info.fp_wr, "%s%s%s\n", tmp_output,
+					"test information for DPDK Cryptodev ",
+					info.device_name);
+			continue;
+		}
+
+		if (i == info.nb_vec_lines - 1) {
+			/** update the time as current time, write to file */
+			fprintf(info.fp_wr, "%s%s\n", "# Generated on ",
+					asctime(tm_now));
+			continue;
+		}
+
+		/* to this point, no field need to update,
+		 *  only copy to rsp file
+		 */
+		fprintf(info.fp_wr, "%s\n", info.vec[i]);
+	}
+
+	return 0;
+}
+
+static int
+parse_file_type(const char *path)
+{
+	const char *tmp = path + strlen(path) - 3;
+
+	if (strstr(tmp, REQ_FILE_PERFIX))
+		info.file_type = FIPS_TYPE_REQ;
+	else if (strstr(tmp, RSP_FILE_PERFIX))
+		info.file_type = FIPS_TYPE_RSP;
+	else if (strstr(path, FAX_FILE_PERFIX))
+		info.file_type = FIPS_TYPE_FAX;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+int
+fips_test_init(const char *req_file_path, const char *rsp_file_path,
+		const char *device_name)
+{
+	if (strcmp(req_file_path, rsp_file_path) == 0) {
+		RTE_LOG(ERR, USER1, "File paths cannot be the same\n");
+		return -EINVAL;
+	}
+
+	fips_test_clear();
+
+	info.algo = FIPS_TEST_ALGO_MAX;
+	if (parse_file_type(req_file_path) < 0) {
+		RTE_LOG(ERR, USER1, "File %s type not supported\n",
+				req_file_path);
+		return -EINVAL;
+	}
+
+	info.fp_rd = fopen(req_file_path, "r");
+	if (!info.fp_rd) {
+		RTE_LOG(ERR, USER1, "Cannot open file %s\n", req_file_path);
+		return -EINVAL;
+	}
+
+	info.fp_wr = fopen(rsp_file_path, "w");
+	if (!info.fp_wr) {
+		RTE_LOG(ERR, USER1, "Cannot open file %s\n", rsp_file_path);
+		return -EINVAL;
+	}
+
+	info.one_line_text = calloc(1, MAX_LINE_CHAR);
+	if (!info.one_line_text) {
+		RTE_LOG(ERR, USER1, "Insufficient memory\n");
+		return -ENOMEM;
+	}
+
+	strlcpy(info.device_name, device_name, sizeof(info.device_name));
+
+	if (fips_test_parse_header() < 0) {
+		RTE_LOG(ERR, USER1, "Failed parsing header\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+void
+fips_test_clear(void)
+{
+	if (info.fp_rd)
+		fclose(info.fp_rd);
+	if (info.fp_wr)
+		fclose(info.fp_wr);
+	if (info.one_line_text)
+		free(info.one_line_text);
+	if (info.nb_vec_lines) {
+		uint32_t i;
+
+		for (i = 0; i < info.nb_vec_lines; i++)
+			free(info.vec[i]);
+	}
+
+	memset(&info, 0, sizeof(info));
+}
+
+int
+fips_test_parse_one_case(void)
+{
+	uint32_t i, j = 0;
+	uint32_t is_interim = 0;
+	int ret;
+
+	if (info.interim_callbacks) {
+		for (i = 0; i < info.nb_vec_lines; i++) {
+			for (j = 0; info.interim_callbacks[j].key != NULL; j++)
+				if (strstr(info.vec[i],
+					info.interim_callbacks[j].key)) {
+					is_interim = 1;
+
+					ret = info.interim_callbacks[j].cb(
+						info.interim_callbacks[j].key,
+						info.vec[i],
+						info.interim_callbacks[j].val);
+					if (ret < 0)
+						return ret;
+				}
+		}
+	}
+
+	if (is_interim) {
+		for (i = 0; i < info.nb_vec_lines; i++)
+			fprintf(info.fp_wr, "%s\n", info.vec[i]);
+		fprintf(info.fp_wr, "\n");
+		return 1;
+	}
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		for (j = 0; info.callbacks[j].key != NULL; j++)
+			if (strstr(info.vec[i], info.callbacks[j].key)) {
+				ret = info.callbacks[j].cb(
+					info.callbacks[j].key,
+					info.vec[i], info.callbacks[j].val);
+				if (ret < 0)
+					return ret;
+				break;
+			}
+	}
+
+	return 0;
+}
+
+void
+fips_test_write_one_case(void)
+{
+	uint32_t i;
+
+	for (i = 0; i < info.nb_vec_lines; i++)
+		fprintf(info.fp_wr, "%s\n", info.vec[i]);
+}
+
+static int
+parser_read_uint64_hex(uint64_t *value, const char *p)
+{
+	char *next;
+	uint64_t val;
+
+	p = skip_white_spaces(p);
+
+	val = strtoul(p, &next, 16);
+	if (p == next)
+		return -EINVAL;
+
+	p = skip_white_spaces(next);
+	if (*p != '\0')
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
+int
+parser_read_uint8_hex(uint8_t *value, const char *p)
+{
+	uint64_t val = 0;
+	int ret = parser_read_uint64_hex(&val, p);
+
+	if (ret < 0)
+		return ret;
+
+	if (val > UINT8_MAX)
+		return -ERANGE;
+
+	*value = val;
+	return 0;
+}
+
+int
+parse_uint8_known_len_hex_str(const char *key, char *src, struct fips_val *val)
+{
+	struct fips_val tmp_val = {0};
+	uint32_t len = val->len;
+	int ret;
+
+	if (len == 0) {
+		if (val->val != NULL) {
+			rte_free(val->val);
+			val->val = NULL;
+		}
+
+		return 0;
+	}
+
+	ret = parse_uint8_hex_str(key, src, &tmp_val);
+	if (ret < 0)
+		return ret;
+
+	if (tmp_val.len == val->len) {
+		val->val = tmp_val.val;
+		return 0;
+	}
+
+	if (tmp_val.len < val->len) {
+		rte_free(tmp_val.val);
+		return -EINVAL;
+	}
+
+	val->val = rte_zmalloc(NULL, val->len, 0);
+	if (!val->val) {
+		rte_free(tmp_val.val);
+		memset(val, 0, sizeof(*val));
+		return -ENOMEM;
+	}
+
+	memcpy(val->val, tmp_val.val, val->len);
+	rte_free(tmp_val.val);
+
+	return 0;
+}
+
+int
+parse_uint8_hex_str(const char *key, char *src, struct fips_val *val)
+{
+	uint32_t len, j;
+
+	src += strlen(key);
+
+	len = strlen(src) / 2;
+
+	if (val->val) {
+		rte_free(val->val);
+		val->val = NULL;
+	}
+
+	val->val = rte_zmalloc(NULL, len, 0);
+	if (!val->val)
+		return -1;
+
+	for (j = 0; j < len; j++) {
+		char byte[3] = {src[j * 2], src[j * 2 + 1], '\0'};
+
+		if (parser_read_uint8_hex(&val->val[j], byte) < 0) {
+			rte_free(val->val);
+			memset(val, 0, sizeof(*val));
+			return -EINVAL;
+		}
+	}
+
+	val->len = len;
+
+	return 0;
+}
+
+int
+parser_read_uint32_val(const char *key, char *src, struct fips_val *val)
+{
+	char *data = src + strlen(key);
+	size_t data_len = strlen(data);
+	int ret;
+
+	if (data[data_len - 1] == ']') {
+		char *tmp_data = calloc(1, data_len + 1);
+
+		if (tmp_data == NULL)
+			return -ENOMEM;
+
+		strlcpy(tmp_data, data, data_len);
+
+		ret = parser_read_uint32(&val->len, tmp_data);
+
+		free(tmp_data);
+	} else
+		ret = parser_read_uint32(&val->len, data);
+
+	return ret;
+}
+
+int
+parser_read_uint32_bit_val(const char *key, char *src, struct fips_val *val)
+{
+	int ret;
+
+	ret = parser_read_uint32_val(key, src, val);
+
+	if (ret < 0)
+		return ret;
+
+	val->len /= 8;
+
+	return 0;
+}
+
+int
+writeback_hex_str(const char *key, char *dst, struct fips_val *val)
+{
+	char *str = dst;
+	uint32_t len;
+
+	str += strlen(key);
+
+	for (len = 0; len < val->len; len++)
+		snprintf(str + len * 2, 255, "%02x", val->val[len]);
+
+	return 0;
+}
+
+static int
+parser_read_uint64(uint64_t *value, const char *p)
+{
+	char *next;
+	uint64_t val;
+
+	p = skip_white_spaces(p);
+	if (!isdigit(*p))
+		return -EINVAL;
+
+	val = strtoul(p, &next, 10);
+	if (p == next)
+		return -EINVAL;
+
+	p = next;
+	switch (*p) {
+	case 'T':
+		val *= 1024ULL;
+		/* fall through */
+	case 'G':
+		val *= 1024ULL;
+		/* fall through */
+	case 'M':
+		val *= 1024ULL;
+		/* fall through */
+	case 'k':
+	case 'K':
+		val *= 1024ULL;
+		p++;
+		break;
+	}
+
+	p = skip_white_spaces(p);
+	if (*p != '\0')
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
+int
+parser_read_uint32(uint32_t *value, char *p)
+{
+	uint64_t val = 0;
+	int ret = parser_read_uint64(&val, p);
+
+	if (ret < 0)
+		return ret;
+
+	if (val > UINT32_MAX)
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
+void
+parse_write_hex_str(struct fips_val *src)
+{
+	writeback_hex_str("", info.one_line_text, src);
+
+	fprintf(info.fp_wr, "%s\n", info.one_line_text);
+}
+
+int
+update_info_vec(uint32_t count)
+{
+	const struct fips_test_callback *cb;
+	uint32_t i, j;
+
+	if (!info.writeback_callbacks)
+		return -1;
+
+	cb = &info.writeback_callbacks[0];
+
+	snprintf(info.vec[0], strlen(info.vec[0]) + 4, "%s%u", cb->key, count);
+
+	for (i = 1; i < info.nb_vec_lines; i++) {
+		for (j = 1; info.writeback_callbacks[j].key != NULL; j++) {
+			cb = &info.writeback_callbacks[j];
+			if (strstr(info.vec[i], cb->key)) {
+				cb->cb(cb->key, info.vec[i], cb->val);
+				break;
+			}
+		}
+	}
+
+	return 0;
+}
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
new file mode 100644
index 0000000..beb6bed
--- /dev/null
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
@@ -0,0 +1,150 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _CRYPTODEV_NIST_FIPS_PARSER_H_
+#define _CRYPTODEV_NIST_FIPS_PARSER_H_
+
+#define FIPS_PARSE_ERR(fmt, args)					\
+	RTE_LOG(ERR, USER1, "FIPS parse error" ## fmt ## "\n", ## args)
+
+#define ERR_MSG_SIZE		128
+#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 MAX_STRING_SIZE		64
+
+#define POSITIVE_TEST		0
+#define NEGATIVE_TEST		-1
+
+#define REQ_FILE_PERFIX		"req"
+#define RSP_FILE_PERFIX		"rsp"
+#define FAX_FILE_PERFIX		"fax"
+
+enum fips_test_algorithms {
+		FIPS_TEST_ALGO_MAX
+};
+
+enum file_types {
+	FIPS_TYPE_REQ = 1,
+	FIPS_TYPE_FAX,
+	FIPS_TYPE_RSP
+};
+
+enum fips_test_op {
+	FIPS_TEST_ENC_AUTH_GEN = 1,
+	FIPS_TEST_DEC_AUTH_VERIF,
+};
+
+#define MAX_LINE_PER_VECTOR            16
+
+struct fips_val {
+	uint8_t *val;
+	uint32_t len;
+};
+
+struct fips_test_vector {
+	union {
+		struct {
+			struct fips_val key;
+			struct fips_val digest;
+			struct fips_val auth_aad;
+			struct fips_val aad;
+		} cipher_auth;
+		struct {
+			struct fips_val key;
+			struct fips_val digest;
+			struct fips_val aad;
+		} aead;
+	};
+
+	struct fips_val pt;
+	struct fips_val ct;
+	struct fips_val iv;
+
+	enum rte_crypto_op_status status;
+};
+
+typedef int (*post_prcess_t)(struct fips_val *val);
+
+typedef int (*parse_callback_t)(const char *key, char *text,
+		struct fips_val *val);
+
+struct fips_test_callback {
+	const char *key;
+	parse_callback_t cb;
+	struct fips_val *val;
+};
+
+struct fips_test_interim_info {
+	FILE *fp_rd;
+	FILE *fp_wr;
+	enum file_types file_type;
+	enum fips_test_algorithms algo;
+	char *one_line_text;
+	char *vec[MAX_LINE_PER_VECTOR];
+	uint32_t nb_vec_lines;
+	//uint8_t cryptodev_id;
+	char device_name[MAX_STRING_SIZE];
+
+	enum fips_test_op op;
+
+	const struct fips_test_callback *callbacks;
+	const struct fips_test_callback *interim_callbacks;
+	const struct fips_test_callback *writeback_callbacks;
+
+	post_prcess_t parse_writeback;
+	post_prcess_t kat_check;
+};
+
+extern struct fips_test_vector vec;
+extern struct fips_test_interim_info info;
+
+int
+fips_test_init(const char *req_file_path, const char *rsp_file_path,
+		const char *device_name);
+
+void
+fips_test_clear(void);
+
+int
+fips_test_fetch_one_block(void);
+
+int
+fips_test_parse_one_case(void);
+
+void
+fips_test_write_one_case(void);
+
+int
+parser_read_uint8_hex(uint8_t *value, const char *p);
+
+int
+parse_uint8_hex_str(const char *key, char *src, struct fips_val *val);
+
+int
+parse_uint8_known_len_hex_str(const char *key, char *src, struct fips_val *val);
+
+int
+parser_read_uint32_val(const char *key, char *src, struct fips_val *val);
+
+int
+parser_read_uint32_bit_val(const char *key, char *src, struct fips_val *val);
+
+int
+parser_read_uint32(uint32_t *value, char *p);
+
+int
+parser_read_uint32_val(const char *key, char *src, struct fips_val *val);
+
+int
+writeback_hex_str(const char *key, char *dst, struct fips_val *val);
+
+void
+parse_write_hex_str(struct fips_val *src);
+
+int
+update_info_vec(uint32_t count);
+
+#endif
diff --git a/examples/cryptodev_fips_validate/main.c b/examples/cryptodev_fips_validate/main.c
new file mode 100644
index 0000000..4f14b04
--- /dev/null
+++ b/examples/cryptodev_fips_validate/main.c
@@ -0,0 +1,388 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <sys/stat.h>
+#include <getopt.h>
+#include <dirent.h>
+
+#include <rte_cryptodev.h>
+#include <rte_cryptodev_pmd.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_string_fns.h>
+
+#include "cryptodev_fips_validate.h"
+
+#define REQ_FILE_PATH_KEYWORD	"req-file"
+#define RSP_FILE_PATH_KEYWORD	"rsp-file"
+#define FOLDER_KEYWORD		"path-is-folder"
+#define CRYPTODEV_KEYWORD	"cryptodev"
+#define CRYPTODEV_ID_KEYWORD	"cryptodev-id"
+
+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;
+	uint32_t dev_id;
+	struct rte_mempool *mpool;
+	struct rte_mempool *op_pool;
+	struct rte_mbuf *mbuf;
+	struct rte_crypto_op *op;
+	struct rte_cryptodev_sym_session *sess;
+} env;
+
+static int
+cryptodev_fips_validate_app_int(void)
+{
+	struct rte_cryptodev_config conf = {rte_socket_id(), 1};
+	struct rte_cryptodev_qp_conf qp_conf = {128};
+	int ret;
+
+	ret = rte_cryptodev_configure(env.dev_id, &conf);
+	if (ret < 0)
+		return ret;
+
+	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", 128, 0, 0,
+			UINT16_MAX, rte_socket_id());
+	if (!env.mpool)
+		return ret;
+
+	ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
+			rte_socket_id(), env.mpool);
+	if (ret < 0)
+		return ret;
+
+	ret = -ENOMEM;
+
+	env.op_pool = rte_crypto_op_pool_create(
+			"FIPS_OP_POOL",
+			RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+			1, 0,
+			16,
+			rte_socket_id());
+	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;
+
+	return 0;
+
+error_exit:
+	rte_mempool_free(env.mpool);
+	if (env.op_pool)
+		rte_mempool_free(env.op_pool);
+
+	return ret;
+}
+
+static void
+cryptodev_fips_validate_app_uninit(void)
+{
+	rte_pktmbuf_free(env.mbuf);
+	rte_crypto_op_free(env.op);
+	rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
+	rte_cryptodev_sym_session_free(env.sess);
+	rte_mempool_free(env.mpool);
+	rte_mempool_free(env.op_pool);
+}
+
+static int
+fips_test_one_file(void);
+
+static int
+parse_cryptodev_arg(char *arg)
+{
+	int id = rte_cryptodev_get_dev_id(arg);
+
+	if (id < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev name %s\n",
+				id, arg);
+		return id;
+	}
+
+	env.dev_id = (uint32_t)id;
+
+	return 0;
+}
+
+static int
+parse_cryptodev_id_arg(char *arg)
+{
+	uint32_t cryptodev_id;
+
+	if (parser_read_uint32(&cryptodev_id, arg) < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n",
+				-EINVAL, arg);
+		return -1;
+	}
+
+
+	if (!rte_cryptodev_pmd_is_valid_dev(cryptodev_id)) {
+		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n",
+				cryptodev_id, arg);
+		return -1;
+	}
+
+	env.dev_id = (uint32_t)cryptodev_id;
+
+	return 0;
+}
+
+static void
+cryptodev_fips_validate_usage(const char *prgname)
+{
+	printf("%s [EAL options] --\n"
+		"  --%s: REQUEST-FILE-PATH\n"
+		"  --%s: RESPONSE-FILE-PATH\n"
+		"  --%s: indicating both paths are folders\n"
+		"  --%s: CRYPTODEV-NAME\n"
+		"  --%s: CRYPTODEV-ID-NAME\n",
+		prgname, REQ_FILE_PATH_KEYWORD, RSP_FILE_PATH_KEYWORD,
+		FOLDER_KEYWORD, CRYPTODEV_KEYWORD, CRYPTODEV_ID_KEYWORD);
+}
+
+static int
+cryptodev_fips_validate_parse_args(int argc, char **argv)
+{
+	int opt, ret;
+	char *prgname = argv[0];
+	char **argvopt;
+	int option_index;
+	struct option lgopts[] = {
+			{REQ_FILE_PATH_KEYWORD, required_argument, 0, 0},
+			{RSP_FILE_PATH_KEYWORD, required_argument, 0, 0},
+			{FOLDER_KEYWORD, no_argument, 0, 0},
+			{CRYPTODEV_KEYWORD, required_argument, 0, 0},
+			{CRYPTODEV_ID_KEYWORD, required_argument, 0, 0},
+			{NULL, 0, 0, 0}
+	};
+
+	argvopt = argv;
+
+	while ((opt = getopt_long(argc, argvopt, "s:",
+				  lgopts, &option_index)) != EOF) {
+
+		switch (opt) {
+		case 0:
+			if (strcmp(lgopts[option_index].name,
+					REQ_FILE_PATH_KEYWORD) == 0)
+				env.req_path = optarg;
+			else if (strcmp(lgopts[option_index].name,
+					RSP_FILE_PATH_KEYWORD) == 0)
+				env.rsp_path = optarg;
+			else if (strcmp(lgopts[option_index].name,
+					FOLDER_KEYWORD) == 0)
+				env.is_path_folder = 1;
+			else if (strcmp(lgopts[option_index].name,
+					CRYPTODEV_KEYWORD) == 0) {
+				ret = parse_cryptodev_arg(optarg);
+				if (ret < 0) {
+					cryptodev_fips_validate_usage(prgname);
+					return -EINVAL;
+				}
+			} else if (strcmp(lgopts[option_index].name,
+					CRYPTODEV_ID_KEYWORD) == 0) {
+				ret = parse_cryptodev_id_arg(optarg);
+				if (ret < 0) {
+					cryptodev_fips_validate_usage(prgname);
+					return -EINVAL;
+				}
+			} else {
+				cryptodev_fips_validate_usage(prgname);
+				return -EINVAL;
+			}
+			break;
+		default:
+			return -1;
+		}
+	}
+
+	if (env.req_path == NULL || env.rsp_path == NULL ||
+			env.dev_id == UINT32_MAX) {
+		cryptodev_fips_validate_usage(prgname);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+	int ret;
+
+	ret = rte_eal_init(argc, argv);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
+		return -1;
+	}
+
+	argc -= ret;
+	argv += ret;
+
+	ret = cryptodev_fips_validate_parse_args(argc, argv);
+	if (ret < 0)
+		rte_exit(EXIT_FAILURE, "Failed to parse arguments!\n");
+
+	ret = cryptodev_fips_validate_app_int();
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
+		return -1;
+	}
+
+	if (!env.is_path_folder) {
+		printf("Processing file %s... ", env.req_path);
+
+		ret = fips_test_init(env.req_path, env.rsp_path,
+			rte_cryptodev_name_get(env.dev_id));
+		if (ret < 0) {
+			RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
+					ret, env.req_path);
+			goto exit;
+		}
+
+
+		ret = fips_test_one_file();
+		if (ret < 0) {
+			RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
+					ret, env.req_path);
+			goto exit;
+		}
+
+		printf("Done\n");
+
+	} else {
+		struct dirent *dir;
+		DIR *d_req, *d_rsp;
+		char req_path[1024];
+		char rsp_path[1024];
+
+		d_req = opendir(env.req_path);
+		if (!d_req) {
+			RTE_LOG(ERR, USER1, "Error %i: Path %s not exist\n",
+					-EINVAL, env.req_path);
+			goto exit;
+		}
+
+		d_rsp = opendir(env.rsp_path);
+		if (!d_rsp) {
+			ret = mkdir(env.rsp_path, 0700);
+			if (ret == 0)
+				d_rsp = opendir(env.rsp_path);
+			else {
+				RTE_LOG(ERR, USER1, "Error %i: Invalid %s\n",
+						-EINVAL, env.rsp_path);
+				goto exit;
+			}
+		}
+		closedir(d_rsp);
+
+		while ((dir = readdir(d_req)) != NULL) {
+			if (strstr(dir->d_name, "req") == NULL)
+				continue;
+
+			snprintf(req_path, 1023, "%s/%s", env.req_path,
+					dir->d_name);
+			snprintf(rsp_path, 1023, "%s/%s", env.rsp_path,
+					dir->d_name);
+			strlcpy(strstr(rsp_path, "req"), "rsp", 4);
+
+			printf("Processing file %s... ", req_path);
+
+			ret = fips_test_init(req_path, rsp_path,
+			rte_cryptodev_name_get(env.dev_id));
+			if (ret < 0) {
+				RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
+						ret, req_path);
+				break;
+			}
+
+			ret = fips_test_one_file();
+			if (ret < 0) {
+				RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
+						ret, req_path);
+				break;
+			}
+
+			printf("Done\n");
+		}
+
+		closedir(d_req);
+	}
+
+
+exit:
+	fips_test_clear();
+	cryptodev_fips_validate_app_uninit();
+
+	return ret;
+
+}
+
+static void
+print_test_block(void)
+{
+	uint32_t i;
+
+	for (i = 0; i < info.nb_vec_lines; i++)
+		printf("%s\n", info.vec[i]);
+
+	printf("\n");
+}
+
+static int
+fips_test_one_file(void)
+{
+	int fetch_ret = 0, ret;
+
+	while (fetch_ret == 0) {
+		fetch_ret = fips_test_fetch_one_block();
+		if (fetch_ret < 0) {
+			RTE_LOG(ERR, USER1, "Error %i: Fetch block\n",
+					fetch_ret);
+			ret = fetch_ret;
+			goto error_one_case;
+		}
+
+		if (info.nb_vec_lines == 0) {
+			if (fetch_ret == -EOF)
+				break;
+
+			fprintf(info.fp_wr, "\n");
+			continue;
+		}
+
+		ret = fips_test_parse_one_case();
+		switch (ret) {
+		case 0:
+			if (ret == 0)
+				break;
+			RTE_LOG(ERR, USER1, "Error %i: test block\n",
+					ret);
+			goto error_one_case;
+		case 1:
+			break;
+		default:
+			RTE_LOG(ERR, USER1, "Error %i: Parse block\n",
+					ret);
+			goto error_one_case;
+		}
+
+		continue;
+error_one_case:
+		print_test_block();
+	}
+
+	fips_test_clear();
+
+}
diff --git a/examples/cryptodev_fips_validate/meson.build b/examples/cryptodev_fips_validate/meson.build
new file mode 100644
index 0000000..f44043c
--- /dev/null
+++ b/examples/cryptodev_fips_validate/meson.build
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Intel Corporation
+
+# meson file, for building this example as part of a main DPDK build.
+#
+# To build this example as a standalone application with an already-installed
+# DPDK instance, use 'make'
+
+deps += ['cryptodev']
+allow_experimental_apis = true
+sources = files(
+	'cryptodev_fips_parse_validate.c',
+	'main.c'
+)
-- 
2.9.5

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

* [dpdk-dev] [PATCH v5 2/8] examples/cryptodev_fips_validate: add aes parser and enablement for test types
  2018-10-17 12:49 ` [dpdk-dev] [PATCH v5 " Marko Kovacevic
  2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 1/8] examples/cryptodev_fips_validate: add fips validation into examples Marko Kovacevic
@ 2018-10-17 12:49   ` Marko Kovacevic
  2018-10-24 12:37     ` Akhil Goyal
  2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 3/8] examples/cryptodev_fips_validate: add hmac parser Marko Kovacevic
                     ` (7 subsequent siblings)
  9 siblings, 1 reply; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-17 12:49 UTC (permalink / raw)
  To: dev; +Cc: roy.fan.zhang, akhil.goyal, arkadiuszx.kusztal, Marko Kovacevic

Added enablement for AES-CBC parser, to allow the
application to parser the aes request file and to validate all
test types supported.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 examples/cryptodev_fips_validate/Makefile          |   1 +
 .../cryptodev_fips_parse_aes.c                     | 186 +++++++++++
 .../cryptodev_fips_parse_validate.c                |   6 +
 .../cryptodev_fips_validate.h                      |  24 ++
 examples/cryptodev_fips_validate/main.c            | 346 ++++++++++++++++++++-
 examples/cryptodev_fips_validate/meson.build       |   1 +
 6 files changed, 563 insertions(+), 1 deletion(-)
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c

diff --git a/examples/cryptodev_fips_validate/Makefile b/examples/cryptodev_fips_validate/Makefile
index 7f0e603..2fc5689 100644
--- a/examples/cryptodev_fips_validate/Makefile
+++ b/examples/cryptodev_fips_validate/Makefile
@@ -5,6 +5,7 @@
 APP = fips_validation
 
 # all source are stored in SRCS-y
+SRCS-y := cryptodev_fips_parse_aes.c
 SRCS-y += cryptodev_fips_parse_validate.c
 SRCS-y += main.c
 
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c
new file mode 100644
index 0000000..39dbd6f
--- /dev/null
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c
@@ -0,0 +1,186 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+
+#include <rte_cryptodev.h>
+
+#include "cryptodev_fips_validate.h"
+
+#define MODE_STR	"AESVS"
+#define ALGO_STR	"test data for "
+#define OP_STR		"State"
+#define KEY_SIZE_STR	"Key Length : "
+
+
+#define COUNT_STR	"COUNT = "
+#define KEY_STR		"KEY = "
+#define IV_STR		"IV = "
+#define PT_STR		"PLAINTEXT = "
+#define CT_STR		"CIPHERTEXT = "
+
+#define OP_ENC_STR	"ENCRYPT"
+#define OP_DEC_STR	"DECRYPT"
+
+struct {
+	uint32_t type;
+	const char *desc;
+} aes_test_types[] = {
+		{AESAVS_TYPE_GFXBOX, "GFSbox"},
+		{AESAVS_TYPE_KEYSBOX, "KeySbox"},
+		{AESAVS_TYPE_VARKEY, "VarKey"},
+		{AESAVS_TYPE_VARTXT, "VarTxt"},
+		{AESAVS_TYPE_MMT, "MMT"},
+		{AESAVS_TYPE_MCT, "MCT"},
+};
+
+struct aes_test_algo {
+	const char *name;
+	enum rte_crypto_cipher_algorithm algo;
+} const algo_con[] = {
+		{"CBC", RTE_CRYPTO_CIPHER_AES_CBC},
+};
+
+static int
+parse_interim_enc_dec(const char *key,
+		__attribute__((__unused__)) char *text,
+		__attribute__((__unused__)) struct fips_val *val)
+{
+	if (strcmp(key, OP_ENC_STR) == 0)
+		info.op = FIPS_TEST_ENC_AUTH_GEN;
+	else if (strcmp(key, OP_DEC_STR) == 0)
+		info.op = FIPS_TEST_DEC_AUTH_VERIF;
+	else
+		return -1;
+
+	return 0;
+}
+
+struct fips_test_callback aes_tests_interim[] = {
+		{OP_ENC_STR, parse_interim_enc_dec, NULL},
+		{OP_DEC_STR, parse_interim_enc_dec, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback aes_tests_vectors[] = {
+		{KEY_STR, parse_uint8_hex_str, &vec.cipher_auth.key},
+		{IV_STR, parse_uint8_hex_str, &vec.iv},
+		{PT_STR, parse_uint8_hex_str, &vec.pt},
+		{CT_STR, parse_uint8_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback aes_tests_interim_vectors[] = {
+		{OP_ENC_STR, parse_interim_enc_dec, NULL},
+		{OP_DEC_STR, parse_interim_enc_dec, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback aes_writeback_callbacks[] = {
+		/** First element is used to pass COUNT string */
+		{COUNT_STR, NULL, NULL},
+		{IV_STR, writeback_hex_str, &vec.iv},
+		{KEY_STR, writeback_hex_str, &vec.cipher_auth.key},
+		{PT_STR, writeback_hex_str, &vec.pt},
+		{CT_STR, writeback_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+static int
+parse_test_aes_writeback(struct fips_val *val)
+{
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN)
+		fprintf(info.fp_wr, "%s", CT_STR);
+	else
+		fprintf(info.fp_wr, "%s", PT_STR);
+
+	parse_write_hex_str(val);
+
+	return 0;
+}
+
+static int
+rsp_test_aes_check(struct fips_val *val)
+{
+	struct fips_val *data;
+
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN)
+		data = &vec.ct;
+	else
+		data = &vec.pt;
+
+	if (memcmp(val->val, data->val, val->len) == 0)
+		fprintf(info.fp_wr, "Success\n");
+	else
+		fprintf(info.fp_wr, "Failed\n");
+
+	return 0;
+}
+
+int
+parse_test_aes_init(void)
+{
+	char *tmp;
+	uint32_t i, j;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		char *line = info.vec[i];
+
+		tmp = strstr(line, MODE_STR);
+		if (tmp) {
+			for (j = 0; j < RTE_DIM(aes_test_types); j++)
+				if (strstr(line, aes_test_types[j].desc)) {
+					info.interim_info.aes_data.test_type =
+							aes_test_types[j].type;
+					break;
+				}
+
+			if (j >= RTE_DIM(aes_test_types))
+				return -EINVAL;
+
+			tmp = strstr(line, ALGO_STR);
+			if (!tmp)
+				return -EINVAL;
+
+			tmp += strlen(ALGO_STR);
+			for (j = 0; j < RTE_DIM(algo_con); j++)
+				if (strcmp(algo_con[j].name, tmp) == 0) {
+					info.interim_info.aes_data.cipher_algo =
+						(uint32_t)algo_con[j].algo;
+					break;
+				}
+			if (j >= RTE_DIM(algo_con))
+				return -EINVAL;
+
+			continue;
+		}
+
+		tmp = strstr(line, OP_STR);
+		if (tmp)
+			continue;
+
+		tmp = strstr(line, KEY_SIZE_STR);
+		if (tmp) {
+			tmp += strlen(KEY_SIZE_STR);
+			if (parser_read_uint32
+					(&info.interim_info.aes_data.key_len,
+							tmp) < 0)
+				return -EINVAL;
+
+			info.interim_info.aes_data.key_len /= 8;
+
+			continue;
+		}
+	}
+
+	info.parse_writeback = parse_test_aes_writeback;
+	info.callbacks = aes_tests_vectors;
+	info.interim_callbacks = aes_tests_interim_vectors;
+	info.writeback_callbacks = aes_writeback_callbacks;
+	info.kat_check = rsp_test_aes_check;
+
+	return 0;
+}
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
index aec5bb9..32af47b 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
@@ -104,6 +104,12 @@ fips_test_parse_header(void)
 		return ret;
 
 	for (i = 0; i < info.nb_vec_lines; i++) {
+		if (strstr(info.vec[i], "AESVS")) {
+			info.algo = FIPS_TEST_ALGO_AES;
+			ret = parse_test_aes_init();
+			if (ret < 0)
+				return ret;
+		}
 
 		tmp = strstr(info.vec[i], "# Config info for ");
 		if (tmp != NULL) {
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
index beb6bed..5ac858d 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
@@ -23,6 +23,7 @@
 #define FAX_FILE_PERFIX		"fax"
 
 enum fips_test_algorithms {
+		FIPS_TEST_ALGO_AES = 0,
 		FIPS_TEST_ALGO_MAX
 };
 
@@ -77,6 +78,21 @@ struct fips_test_callback {
 	struct fips_val *val;
 };
 
+enum fips_aesavs_test_types {
+	AESAVS_TYPE_GFXBOX = 0,
+	AESAVS_TYPE_KEYSBOX,
+	AESAVS_TYPE_VARKEY,
+	AESAVS_TYPE_VARTXT,
+	AESAVS_TYPE_MMT,
+	AESAVS_TYPE_MCT,
+};
+
+struct aesavs_interim_data {
+	enum fips_aesavs_test_types test_type;
+	uint32_t cipher_algo;
+	uint32_t key_len;
+};
+
 struct fips_test_interim_info {
 	FILE *fp_rd;
 	FILE *fp_wr;
@@ -88,6 +104,11 @@ struct fips_test_interim_info {
 	//uint8_t cryptodev_id;
 	char device_name[MAX_STRING_SIZE];
 
+	union {
+		struct aesavs_interim_data aes_data;
+
+	} interim_info;
+
 	enum fips_test_op op;
 
 	const struct fips_test_callback *callbacks;
@@ -118,6 +139,9 @@ void
 fips_test_write_one_case(void);
 
 int
+parse_test_aes_init(void);
+
+int
 parser_read_uint8_hex(uint8_t *value, const char *p);
 
 int
diff --git a/examples/cryptodev_fips_validate/main.c b/examples/cryptodev_fips_validate/main.c
index 4f14b04..98d70b4 100644
--- a/examples/cryptodev_fips_validate/main.c
+++ b/examples/cryptodev_fips_validate/main.c
@@ -329,6 +329,340 @@ 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;
+
+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);
+
+	__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;
+
+	memcpy(iv, vec.iv.val, 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);
+
+		if (!pt) {
+			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
+					-ENOMEM);
+			return -ENOMEM;
+		}
+
+		memcpy(pt, vec.pt.val, vec.pt.len);
+		sym->cipher.data.length = vec.pt.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;
+		}
+
+		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;
+		}
+
+		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);
+
+	return 0;
+}
+
+static int
+prepare_aes_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_cipher_xform *cipher_xform = &xform->cipher;
+
+	xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+
+	cipher_xform->algo = RTE_CRYPTO_CIPHER_AES_CBC;
+	cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_CIPHER_OP_ENCRYPT :
+			RTE_CRYPTO_CIPHER_OP_DECRYPT;
+	cipher_xform->key.data = vec.cipher_auth.key.val;
+	cipher_xform->key.length = vec.cipher_auth.key.len;
+	cipher_xform->iv.length = vec.iv.len;
+	cipher_xform->iv.offset = IV_OFF;
+
+	cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_AES_CBC;
+	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;
+	}
+
+	return 0;
+}
+
+static void
+get_writeback_data(struct fips_val *val)
+{
+	val->val = rte_pktmbuf_mtod(env.mbuf, uint8_t *);
+	val->len = rte_pktmbuf_pkt_len(env.mbuf);
+}
+
+static int
+fips_run_test(void)
+{
+	struct rte_crypto_sym_xform xform = {0};
+	uint16_t n_deqd;
+	int ret;
+
+	ret = test_ops.prepare_xform(&xform);
+	if (ret < 0)
+		return ret;
+
+	env.sess = rte_cryptodev_sym_session_create(env.mpool);
+	if (!env.sess)
+		return -ENOMEM;
+
+	ret = rte_cryptodev_sym_session_init(env.dev_id,
+			env.sess, &xform, env.mpool);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: Init session\n",
+				ret);
+		return ret;
+	}
+
+	ret = test_ops.prepare_op();
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
+				ret);
+		return ret;
+	}
+
+	if (rte_cryptodev_enqueue_burst(env.dev_id, 0, &env.op, 1) < 1) {
+		RTE_LOG(ERR, USER1, "Error: Failed enqueue\n");
+		return ret;
+	}
+
+	do {
+		struct rte_crypto_op *deqd_op;
+
+		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
+				1);
+	} while (n_deqd == 0);
+
+	vec.status = env.op->status;
+
+	rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
+	rte_cryptodev_sym_session_free(env.sess);
+	env.sess = NULL;
+
+	return ret;
+}
+
+static int
+fips_generic_test(void)
+{
+	struct fips_val val;
+	int ret;
+
+	fips_test_write_one_case();
+
+	ret = fips_run_test();
+	if (ret < 0) {
+		if (ret == -EPERM) {
+			fprintf(info.fp_wr, "Bypass\n\n");
+			return 0;
+		}
+
+		return ret;
+	}
+
+	get_writeback_data(&val);
+
+	switch (info.file_type) {
+	case FIPS_TYPE_REQ:
+	case FIPS_TYPE_RSP:
+		if (info.parse_writeback == NULL)
+			return -EPERM;
+		ret = info.parse_writeback(&val);
+		if (ret < 0)
+			return ret;
+		break;
+	case FIPS_TYPE_FAX:
+		if (info.kat_check == NULL)
+			return -EPERM;
+		ret = info.kat_check(&val);
+		if (ret < 0)
+			return ret;
+		break;
+	}
+
+	fprintf(info.fp_wr, "\n");
+
+	return 0;
+}
+
+static int
+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;
+	uint8_t prev_out[AES_BLOCK_SIZE] = {0};
+	uint8_t prev_in[AES_BLOCK_SIZE] = {0};
+	uint32_t i, j, k;
+	int ret;
+
+	for (i = 0; i < AES_EXTERN_ITER; i++) {
+		if (i != 0)
+			update_info_vec(i);
+
+		fips_test_write_one_case();
+
+		for (j = 0; j < AES_INTERN_ITER; j++) {
+			ret = fips_run_test();
+			if (ret < 0) {
+				if (ret == -EPERM) {
+					fprintf(info.fp_wr, "Bypass\n");
+					return 0;
+				}
+
+				return ret;
+			}
+
+			get_writeback_data(&val);
+
+			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
+				memcpy(prev_in, vec.ct.val, AES_BLOCK_SIZE);
+
+			if (j == 0) {
+				memcpy(prev_out, val.val, AES_BLOCK_SIZE);
+
+				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+					memcpy(vec.pt.val, vec.iv.val,
+							AES_BLOCK_SIZE);
+					memcpy(vec.iv.val, val.val,
+							AES_BLOCK_SIZE);
+				} else {
+					memcpy(vec.ct.val, vec.iv.val,
+							AES_BLOCK_SIZE);
+					memcpy(vec.iv.val, prev_in,
+							AES_BLOCK_SIZE);
+				}
+				continue;
+			}
+
+			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+				memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
+				memcpy(vec.pt.val, prev_out, AES_BLOCK_SIZE);
+			} else {
+				memcpy(vec.iv.val, prev_in, AES_BLOCK_SIZE);
+				memcpy(vec.ct.val, prev_out, AES_BLOCK_SIZE);
+			}
+
+			if (j == AES_INTERN_ITER - 1)
+				continue;
+
+			memcpy(prev_out, val.val, AES_BLOCK_SIZE);
+		}
+
+		info.parse_writeback(&val);
+		fprintf(info.fp_wr, "\n");
+
+		if (i == AES_EXTERN_ITER - 1)
+			continue;
+
+		/** update key */
+		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
+		for (k = 0; k < vec.cipher_auth.key.len; k++) {
+			switch (vec.cipher_auth.key.len) {
+			case 16:
+				val_key.val[k] ^= val.val[k];
+				break;
+			case 24:
+				if (k < 8)
+					val_key.val[k] ^= prev_out[k + 8];
+				else
+					val_key.val[k] ^= val.val[k - 8];
+				break;
+			case 32:
+				if (k < 16)
+					val_key.val[k] ^= prev_out[k];
+				else
+					val_key.val[k] ^= val.val[k - 16];
+				break;
+			default:
+				return -1;
+			}
+		}
+
+		if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
+			memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
+	}
+
+	return 0;
+}
+
+static int
+init_test_ops(void)
+{
+	switch (info.algo) {
+	case FIPS_TEST_ALGO_AES:
+		test_ops.prepare_op = prepare_cipher_op;
+		test_ops.prepare_xform  = prepare_aes_xform;
+		if (info.interim_info.aes_data.test_type == AESAVS_TYPE_MCT)
+			test_ops.test = fips_mct_aes_test;
+		else
+			test_ops.test = fips_generic_test;
+		break;
+
+	default:
+		return -1;
+	}
+
+	return 0;
+}
+
 static void
 print_test_block(void)
 {
@@ -345,7 +679,14 @@ fips_test_one_file(void)
 {
 	int fetch_ret = 0, ret;
 
-	while (fetch_ret == 0) {
+
+	ret = init_test_ops();
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: Init test op\n", ret);
+		return ret;
+	}
+
+	while (ret >= 0 && fetch_ret == 0) {
 		fetch_ret = fips_test_fetch_one_block();
 		if (fetch_ret < 0) {
 			RTE_LOG(ERR, USER1, "Error %i: Fetch block\n",
@@ -365,6 +706,7 @@ fips_test_one_file(void)
 		ret = fips_test_parse_one_case();
 		switch (ret) {
 		case 0:
+			ret = test_ops.test();
 			if (ret == 0)
 				break;
 			RTE_LOG(ERR, USER1, "Error %i: test block\n",
@@ -385,4 +727,6 @@ fips_test_one_file(void)
 
 	fips_test_clear();
 
+	return ret;
+
 }
diff --git a/examples/cryptodev_fips_validate/meson.build b/examples/cryptodev_fips_validate/meson.build
index f44043c..b8c662e 100644
--- a/examples/cryptodev_fips_validate/meson.build
+++ b/examples/cryptodev_fips_validate/meson.build
@@ -9,6 +9,7 @@
 deps += ['cryptodev']
 allow_experimental_apis = true
 sources = files(
+	'cryptodev_fips_parse_aes.c',
 	'cryptodev_fips_parse_validate.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v5 3/8] examples/cryptodev_fips_validate: add hmac parser
  2018-10-17 12:49 ` [dpdk-dev] [PATCH v5 " Marko Kovacevic
  2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 1/8] examples/cryptodev_fips_validate: add fips validation into examples Marko Kovacevic
  2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 2/8] examples/cryptodev_fips_validate: add aes parser and enablement for test types Marko Kovacevic
@ 2018-10-17 12:49   ` Marko Kovacevic
  2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 4/8] examples/cryptodev_fips_validate: add TDES parser and enablement for test types Marko Kovacevic
                     ` (6 subsequent siblings)
  9 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-17 12:49 UTC (permalink / raw)
  To: dev; +Cc: roy.fan.zhang, akhil.goyal, arkadiuszx.kusztal, Marko Kovacevic

Added enablement for HMAC parser, to allow the
application to parser the hmac request files and to validate all
tests supported

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 examples/cryptodev_fips_validate/Makefile          |   1 +
 .../cryptodev_fips_parse_hmac.c                    | 105 +++++++++++++++++++++
 .../cryptodev_fips_parse_validate.c                |   5 +
 .../cryptodev_fips_validate.h                      |   9 ++
 examples/cryptodev_fips_validate/main.c            | 103 ++++++++++++++++++++
 examples/cryptodev_fips_validate/meson.build       |   1 +
 6 files changed, 224 insertions(+)
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_hmac.c

diff --git a/examples/cryptodev_fips_validate/Makefile b/examples/cryptodev_fips_validate/Makefile
index 2fc5689..c85c76c 100644
--- a/examples/cryptodev_fips_validate/Makefile
+++ b/examples/cryptodev_fips_validate/Makefile
@@ -6,6 +6,7 @@ APP = fips_validation
 
 # all source are stored in SRCS-y
 SRCS-y := cryptodev_fips_parse_aes.c
+SRCS-y += cryptodev_fips_parse_hmac.c
 SRCS-y += cryptodev_fips_parse_validate.c
 SRCS-y += main.c
 
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_hmac.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_hmac.c
new file mode 100644
index 0000000..2fbc246
--- /dev/null
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_hmac.c
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+
+#include <rte_cryptodev.h>
+
+#include "cryptodev_fips_validate.h"
+
+#define ALGO_PREFIX	"[L="
+#define KEYLEN_STR	"Klen = "
+#define TAGLEN_STR	"Tlen = "
+
+#define COUNT_STR	"Count = "
+#define KEY_STR		"Key = "
+#define PT_STR		"Msg = "
+#define TAG_STR		"Mac = "
+
+struct hash_size_conversion {
+	const char *str;
+	enum rte_crypto_auth_algorithm algo;
+} hsc[] = {
+		{"20", RTE_CRYPTO_AUTH_SHA1_HMAC},
+		{"28", RTE_CRYPTO_AUTH_SHA224_HMAC},
+		{"32", RTE_CRYPTO_AUTH_SHA256_HMAC},
+		{"48", RTE_CRYPTO_AUTH_SHA384_HMAC},
+		{"64", RTE_CRYPTO_AUTH_SHA512_HMAC},
+};
+
+static int
+parse_interim_algo(__attribute__((__unused__)) const char *key,
+		char *text,
+		__attribute__((__unused__)) struct fips_val *val)
+{
+
+	uint32_t i;
+
+	for (i = 0; i < RTE_DIM(hsc); i++) {
+		if (strstr(text, hsc[i].str)) {
+			info.interim_info.hmac_data.algo = hsc[i].algo;
+			break;
+		}
+	}
+
+	if (i == RTE_DIM(hsc))
+		return -1;
+
+	return 0;
+}
+
+struct fips_test_callback hmac_tests_vectors[] = {
+		{KEYLEN_STR, parser_read_uint32_val, &vec.cipher_auth.key},
+		{TAGLEN_STR, parser_read_uint32_val, &vec.cipher_auth.digest},
+		{KEY_STR, parse_uint8_hex_str, &vec.cipher_auth.key},
+		{PT_STR, parse_uint8_hex_str, &vec.pt},
+		{TAG_STR, parse_uint8_hex_str, &vec.cipher_auth.digest},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback hmac_tests_interim_vectors[] = {
+		{ALGO_PREFIX, parse_interim_algo, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+static int
+parse_test_hmac_writeback(struct fips_val *val)
+{
+	struct fips_val val_local;
+
+	fprintf(info.fp_wr, "%s", TAG_STR);
+
+	val_local.val = val->val + vec.pt.len;
+	val_local.len = vec.cipher_auth.digest.len;
+
+	parse_write_hex_str(&val_local);
+	return 0;
+}
+
+static int
+rsp_test_hmac_check(struct fips_val *val)
+{
+	if (memcmp(val->val + vec.pt.len, vec.cipher_auth.digest.val,
+			vec.cipher_auth.digest.len) == 0)
+		fprintf(info.fp_wr, "Success\n");
+	else
+		fprintf(info.fp_wr, "Failed\n");
+
+	return 0;
+}
+
+int
+parse_test_hmac_init(void)
+{
+	info.op = FIPS_TEST_ENC_AUTH_GEN;
+	info.parse_writeback = parse_test_hmac_writeback;
+	info.callbacks = hmac_tests_vectors;
+	info.interim_callbacks = hmac_tests_interim_vectors;
+	info.writeback_callbacks = NULL;
+	info.kat_check = rsp_test_hmac_check;
+
+	return 0;
+}
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
index 32af47b..f1cd802 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
@@ -109,6 +109,11 @@ fips_test_parse_header(void)
 			ret = parse_test_aes_init();
 			if (ret < 0)
 				return ret;
+		} else if (strstr(info.vec[i], "HMAC")) {
+			info.algo = FIPS_TEST_ALGO_HMAC;
+			ret = parse_test_hmac_init();
+			if (ret < 0)
+				return ret;
 		}
 
 		tmp = strstr(info.vec[i], "# Config info for ");
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
index 5ac858d..3cda9fe 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
@@ -24,6 +24,7 @@
 
 enum fips_test_algorithms {
 		FIPS_TEST_ALGO_AES = 0,
+		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_MAX
 };
 
@@ -93,6 +94,10 @@ struct aesavs_interim_data {
 	uint32_t key_len;
 };
 
+struct hmac_interim_data {
+	enum rte_crypto_auth_algorithm algo;
+};
+
 struct fips_test_interim_info {
 	FILE *fp_rd;
 	FILE *fp_wr;
@@ -106,6 +111,7 @@ struct fips_test_interim_info {
 
 	union {
 		struct aesavs_interim_data aes_data;
+		struct hmac_interim_data hmac_data;
 
 	} interim_info;
 
@@ -142,6 +148,9 @@ int
 parse_test_aes_init(void);
 
 int
+parse_test_hmac_init(void);
+
+int
 parser_read_uint8_hex(uint8_t *value, const char *p);
 
 int
diff --git a/examples/cryptodev_fips_validate/main.c b/examples/cryptodev_fips_validate/main.c
index 98d70b4..a165576 100644
--- a/examples/cryptodev_fips_validate/main.c
+++ b/examples/cryptodev_fips_validate/main.c
@@ -401,6 +401,67 @@ prepare_cipher_op(void)
 }
 
 static int
+prepare_auth_op(void)
+{
+	struct rte_crypto_sym_op *sym = env.op->sym;
+
+	__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;
+
+	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.cipher_auth.digest.len);
+
+		if (!pt) {
+			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
+					-ENOMEM);
+			return -ENOMEM;
+		}
+
+		memcpy(pt, vec.pt.val, vec.pt.len);
+		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);
+
+	} 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 + vec.cipher_auth.digest.len);
+
+		if (!ct) {
+			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
+					-ENOMEM);
+			return -ENOMEM;
+		}
+
+		memcpy(ct, vec.ct.val, vec.ct.len);
+		sym->auth.data.length = vec.ct.len;
+		sym->auth.digest.data = vec.cipher_auth.digest.val;
+		sym->auth.digest.phys_addr = rte_malloc_virt2iova(
+				sym->auth.digest.data);
+	}
+
+	rte_crypto_op_attach_sym_session(env.op, env.sess);
+}
+
+static int
 prepare_aes_xform(struct rte_crypto_sym_xform *xform)
 {
 	const struct rte_cryptodev_symmetric_capability *cap;
@@ -440,6 +501,43 @@ prepare_aes_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_hmac_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 = info.interim_info.hmac_data.algo;
+	auth_xform->op = RTE_CRYPTO_AUTH_OP_GENERATE;
+	auth_xform->digest_length = vec.cipher_auth.digest.len;
+	auth_xform->key.data = vec.cipher_auth.key.val;
+	auth_xform->key.length = vec.cipher_auth.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 void
 get_writeback_data(struct fips_val *val)
 {
@@ -655,6 +753,11 @@ init_test_ops(void)
 		else
 			test_ops.test = fips_generic_test;
 		break;
+	case FIPS_TEST_ALGO_HMAC:
+		test_ops.prepare_op = prepare_auth_op;
+		test_ops.prepare_xform = prepare_hmac_xform;
+		test_ops.test = fips_generic_test;
+		break;
 
 	default:
 		return -1;
diff --git a/examples/cryptodev_fips_validate/meson.build b/examples/cryptodev_fips_validate/meson.build
index b8c662e..3e06f59 100644
--- a/examples/cryptodev_fips_validate/meson.build
+++ b/examples/cryptodev_fips_validate/meson.build
@@ -10,6 +10,7 @@ deps += ['cryptodev']
 allow_experimental_apis = true
 sources = files(
 	'cryptodev_fips_parse_aes.c',
+	'cryptodev_fips_parse_hmac.c',
 	'cryptodev_fips_parse_validate.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v5 4/8] examples/cryptodev_fips_validate: add TDES parser and enablement for test types
  2018-10-17 12:49 ` [dpdk-dev] [PATCH v5 " Marko Kovacevic
                     ` (2 preceding siblings ...)
  2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 3/8] examples/cryptodev_fips_validate: add hmac parser Marko Kovacevic
@ 2018-10-17 12:49   ` Marko Kovacevic
  2018-10-24 12:31     ` Akhil Goyal
  2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 5/8] examples/cryptodev_fips_validate: add gcm parser Marko Kovacevic
                     ` (5 subsequent siblings)
  9 siblings, 1 reply; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-17 12:49 UTC (permalink / raw)
  To: dev; +Cc: roy.fan.zhang, akhil.goyal, arkadiuszx.kusztal, Marko Kovacevic

Added enablement for TDES parser, to allow the
application to parser the TDES request files and to validate all
test types supported.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 examples/cryptodev_fips_validate/Makefile          |   1 +
 .../cryptodev_fips_parse_3des.c                    | 259 +++++++++++++++++++++
 .../cryptodev_fips_parse_aes.c                     |   2 +
 .../cryptodev_fips_parse_validate.c                |   5 +
 .../cryptodev_fips_validate.h                      |  21 ++
 examples/cryptodev_fips_validate/main.c            | 175 ++++++++++++++
 examples/cryptodev_fips_validate/meson.build       |   1 +
 7 files changed, 464 insertions(+)
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c

diff --git a/examples/cryptodev_fips_validate/Makefile b/examples/cryptodev_fips_validate/Makefile
index c85c76c..2ddf326 100644
--- a/examples/cryptodev_fips_validate/Makefile
+++ b/examples/cryptodev_fips_validate/Makefile
@@ -7,6 +7,7 @@ APP = fips_validation
 # all source are stored in SRCS-y
 SRCS-y := cryptodev_fips_parse_aes.c
 SRCS-y += cryptodev_fips_parse_hmac.c
+SRCS-y += cryptodev_fips_parse_3des.c
 SRCS-y += cryptodev_fips_parse_validate.c
 SRCS-y += main.c
 
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c
new file mode 100644
index 0000000..82e9132
--- /dev/null
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c
@@ -0,0 +1,259 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include <rte_malloc.h>
+#include <rte_cryptodev.h>
+
+#include "cryptodev_fips_validate.h"
+
+#define NEW_LINE_STR	"#"
+#define TEST_TYPE_KEY	" for CBC"
+#define TEST_CBCI_KEY	" for CBCI"
+
+#define ENC_STR		"[ENCRYPT]"
+#define DEC_STR		"[DECRYPT]"
+
+#define COUNT_STR	"COUNT = "
+#define KEY1_STR	"KEY1 = "
+#define KEY2_STR	"KEY2 = "
+#define KEY3_STR	"KEY3 = "
+
+#define KEYS_STR	"KEYs = "
+#define IV_STR		"IV = "
+#define PT_STR		"PLAINTEXT = "
+#define CT_STR		"CIPHERTEXT = "
+#define NK_STR		"NumKeys = "
+
+#define SET_STR		" = "
+
+#define PLAIN_TEXT	0
+#define CIPHER_TEXT	1
+#define KEY_TEXT	2
+#define IV_TEXT		3
+
+#define DEVICE_STR	"# Config Info for : "
+
+struct {
+	uint32_t type;
+	const char *desc;
+} test_types[] = {
+		{TDES_INVERSE_PERMUTATION, "INVERSE PERMUTATION"},
+		{TDES_PERMUTATION, "PERMUTATION OPERATION"},
+		{TDES_SUBSTITUTION_TABLE, "SUBSTITUTION TABLE"},
+		{TDES_VARIABLE_KEY, "VARIABLE KEY"},
+		{TDES_VARIABLE_TEXT, "VARIABLE PLAINTEXT/CIPHERTEXT"},
+		{TDES_VARIABLE_TEXT, "KAT"},
+		{TDES_MCT, "Monte Carlo (Modes) Test"},
+		{TDES_MMT, "Multi block Message Test"},
+};
+
+static int
+writeback_tdes_hex_str(const char *key, char *dst, struct fips_val *val);
+
+static int
+parse_3des_uint8_hex_str(const char *key, char *src, struct fips_val *val);
+
+static int
+parse_tdes_interim(const char *key,
+		__attribute__((__unused__)) char *text,
+		struct fips_val *val);
+
+struct fips_test_callback tdes_tests_vectors[] = {
+		{KEYS_STR, parse_3des_uint8_hex_str, &vec.cipher_auth.key},
+		{KEY1_STR, parse_3des_uint8_hex_str, &vec.cipher_auth.key},
+		{KEY2_STR, parse_3des_uint8_hex_str, &vec.cipher_auth.key},
+		{KEY3_STR, parse_3des_uint8_hex_str, &vec.cipher_auth.key},
+		{IV_STR, parse_uint8_hex_str, &vec.iv},
+		{PT_STR, parse_uint8_hex_str, &vec.pt},
+		{CT_STR, parse_uint8_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback tdes_tests_interim_vectors[] = {
+		{ENC_STR, parse_tdes_interim, NULL},
+		{DEC_STR, parse_tdes_interim, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback tdes_writeback_callbacks[] = {
+		/** First element is used to pass COUNT string */
+		{COUNT_STR, NULL, NULL},
+		{IV_STR, writeback_hex_str, &vec.iv},
+		{KEY1_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
+		{KEY2_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
+		{KEY3_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
+		{KEYS_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
+		{PT_STR, writeback_hex_str, &vec.pt},
+		{CT_STR, writeback_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+static int
+parse_tdes_interim(const char *key,
+		__attribute__((__unused__)) char *text,
+		__attribute__((__unused__)) struct fips_val *val)
+{
+	if (strstr(key, ENC_STR))
+		info.op = FIPS_TEST_ENC_AUTH_GEN;
+	else if (strstr(key, DEC_STR))
+		info.op = FIPS_TEST_DEC_AUTH_VERIF;
+	else if (strstr(NK_STR, "NumKeys = 1"))
+		info.interim_info.tdes_data.nb_keys = 1;
+	else if (strstr(NK_STR, "NumKeys = 2"))
+		info.interim_info.tdes_data.nb_keys = 2;
+	else if (strstr(NK_STR, "NumKeys = 3"))
+		info.interim_info.tdes_data.nb_keys = 3;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int
+parse_3des_uint8_hex_str(const char *key, char *src, struct fips_val *val)
+{
+	uint8_t tmp_key[24] = {0};
+	uint32_t len, i;
+
+	src += strlen(key);
+
+	len = strlen(src) / 2;
+
+	if (val->val) {
+		memcpy(tmp_key, val->val, val->len);
+		rte_free(val->val);
+	}
+
+	val->val = rte_zmalloc(NULL, 24, 0);
+	if (!val->val)
+		return -1;
+
+	memcpy(val->val, tmp_key, 24);
+
+	if (strstr(key, KEYS_STR)) {
+		for (i = 0; i < len; i++) {
+			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
+
+			if (parser_read_uint8_hex(&val->val[i], byte) < 0)
+				return -EINVAL;
+		}
+
+		memcpy(val->val + 8, val->val, 8);
+		memcpy(val->val + 16, val->val, 8);
+
+	} else if (strstr(key, KEY1_STR)) {
+		for (i = 0; i < len; i++) {
+			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
+
+			if (parser_read_uint8_hex(&val->val[i], byte) < 0)
+				return -EINVAL;
+		}
+
+		if (info.interim_info.tdes_data.nb_keys == 2)
+			memcpy(val->val + 16, val->val, 8);
+
+	} else if (strstr(key, KEY2_STR)) {
+		for (i = 0; i < len; i++) {
+			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
+
+			if (parser_read_uint8_hex(&val->val[i + 8], byte) < 0)
+				return -EINVAL;
+		}
+
+	} else if (strstr(key, KEY3_STR)) {
+		for (i = 0; i < len; i++) {
+			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
+
+			if (parser_read_uint8_hex(&val->val[i + 16], byte) < 0)
+				return -EINVAL;
+		}
+	} else
+		return -EINVAL;
+
+	val->len = 24;
+
+	return 0;
+}
+
+static int
+parse_test_tdes_writeback(struct fips_val *val)
+{
+
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN)
+		fprintf(info.fp_wr, "%s", CT_STR);
+	else
+		fprintf(info.fp_wr, "%s", PT_STR);
+
+	parse_write_hex_str(val);
+
+	return 0;
+
+}
+
+static int
+writeback_tdes_hex_str(const char *key, char *dst, struct fips_val *val)
+{
+	struct fips_val tmp_val;
+
+	tmp_val.len = 8;
+
+	if (strstr(key, KEY1_STR))
+		tmp_val.val = val->val;
+	else if (strstr(key, KEY2_STR))
+		tmp_val.val = val->val + 8;
+	else if (strstr(key, KEY3_STR))
+		tmp_val.val = val->val + 16;
+
+	return writeback_hex_str(key, dst, &tmp_val);
+}
+
+static int
+rsp_test_tdes_check(struct fips_val *val)
+{
+	struct fips_val *data;
+
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN)
+		data = &vec.ct;
+	else
+		data = &vec.pt;
+
+	if (memcmp(val->val, data->val, val->len) == 0)
+		fprintf(info.fp_wr, "Success\n");
+	else
+		fprintf(info.fp_wr, "Failed\n");
+
+	return 0;
+}
+
+int
+parse_test_tdes_init(void)
+{
+	uint32_t i;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		char *line = info.vec[i];
+		uint32_t j;
+
+		if (strstr(line, TEST_CBCI_KEY))
+			return -EPERM;
+
+		for (j = 0; j < RTE_DIM(test_types); j++)
+			if (strstr(line, test_types[j].desc)) {
+				info.interim_info.tdes_data.test_type =
+						test_types[j].type;
+				break;
+			}
+	}
+
+	info.parse_writeback = parse_test_tdes_writeback;
+	info.callbacks = tdes_tests_vectors;
+	info.interim_callbacks = tdes_tests_interim_vectors;
+	info.writeback_callbacks = tdes_writeback_callbacks;
+	info.kat_check = rsp_test_tdes_check;
+
+	return 0;
+}
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c
index 39dbd6f..cc27754 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c
@@ -33,6 +33,8 @@ struct {
 		{AESAVS_TYPE_KEYSBOX, "KeySbox"},
 		{AESAVS_TYPE_VARKEY, "VarKey"},
 		{AESAVS_TYPE_VARTXT, "VarTxt"},
+		{TDES_VARIABLE_TEXT, "VARIABLE PLAINTEXT/CIPHERTEXT"},
+		{TDES_VARIABLE_TEXT, "KAT"},
 		{AESAVS_TYPE_MMT, "MMT"},
 		{AESAVS_TYPE_MCT, "MCT"},
 };
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
index f1cd802..bb396e5 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
@@ -114,6 +114,11 @@ fips_test_parse_header(void)
 			ret = parse_test_hmac_init();
 			if (ret < 0)
 				return ret;
+		} else if (strstr(info.vec[i], "TDES")) {
+			info.algo = FIPS_TEST_ALGO_TDES;
+			ret = parse_test_tdes_init();
+			if (ret < 0)
+				return 0;
 		}
 
 		tmp = strstr(info.vec[i], "# Config info for ");
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
index 3cda9fe..c9b11dd 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
@@ -25,6 +25,7 @@
 enum fips_test_algorithms {
 		FIPS_TEST_ALGO_AES = 0,
 		FIPS_TEST_ALGO_HMAC,
+		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_MAX
 };
 
@@ -88,6 +89,17 @@ enum fips_aesavs_test_types {
 	AESAVS_TYPE_MCT,
 };
 
+enum fips_tdes_test_types {
+	TDES_INVERSE_PERMUTATION = 0,
+	TDES_PERMUTATION,
+	TDES_SUBSTITUTION_TABLE,
+	TDES_VARIABLE_KEY,
+	TDES_VARIABLE_TEXT,
+	TDES_KAT,
+	TDES_MCT, /* Monte Carlo (Modes) Test */
+	TDES_MMT /* Multi block Message Test */
+};
+
 struct aesavs_interim_data {
 	enum fips_aesavs_test_types test_type;
 	uint32_t cipher_algo;
@@ -98,6 +110,11 @@ struct hmac_interim_data {
 	enum rte_crypto_auth_algorithm algo;
 };
 
+struct tdes_interim_data {
+	enum fips_tdes_test_types test_type;
+	uint32_t nb_keys;
+};
+
 struct fips_test_interim_info {
 	FILE *fp_rd;
 	FILE *fp_wr;
@@ -112,6 +129,7 @@ struct fips_test_interim_info {
 	union {
 		struct aesavs_interim_data aes_data;
 		struct hmac_interim_data hmac_data;
+		struct tdes_interim_data tdes_data;
 
 	} interim_info;
 
@@ -148,6 +166,9 @@ int
 parse_test_aes_init(void);
 
 int
+parse_test_tdes_init(void);
+
+int
 parse_test_hmac_init(void);
 
 int
diff --git a/examples/cryptodev_fips_validate/main.c b/examples/cryptodev_fips_validate/main.c
index a165576..245c40a 100644
--- a/examples/cryptodev_fips_validate/main.c
+++ b/examples/cryptodev_fips_validate/main.c
@@ -502,6 +502,46 @@ prepare_aes_xform(struct rte_crypto_sym_xform *xform)
 }
 
 static int
+prepare_tdes_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_cipher_xform *cipher_xform = &xform->cipher;
+
+	xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+
+	cipher_xform->algo = RTE_CRYPTO_CIPHER_3DES_CBC;
+	cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_CIPHER_OP_ENCRYPT :
+			RTE_CRYPTO_CIPHER_OP_DECRYPT;
+	cipher_xform->key.data = vec.cipher_auth.key.val;
+	cipher_xform->key.length = vec.cipher_auth.key.len;
+	cipher_xform->iv.length = vec.iv.len;
+	cipher_xform->iv.offset = IV_OFF;
+
+	cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_3DES_CBC;
+	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;
+	}
+
+	return 0;
+}
+
+static int
 prepare_hmac_xform(struct rte_crypto_sym_xform *xform)
 {
 	const struct rte_cryptodev_symmetric_capability *cap;
@@ -640,6 +680,133 @@ fips_generic_test(void)
 }
 
 static int
+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;
+	uint8_t prev_out[TDES_BLOCK_SIZE];
+	uint8_t prev_prev_out[TDES_BLOCK_SIZE];
+	uint8_t prev_in[TDES_BLOCK_SIZE];
+	uint32_t i, j, k;
+	int ret;
+
+	for (i = 0; i < TDES_EXTERN_ITER; i++) {
+		if (i != 0)
+			update_info_vec(i);
+
+		fips_test_write_one_case();
+
+		for (j = 0; j < TDES_INTERN_ITER; j++) {
+			ret = fips_run_test();
+			if (ret < 0) {
+				if (ret == -EPERM) {
+					fprintf(info.fp_wr, "Bypass\n");
+					return 0;
+				}
+
+				return ret;
+			}
+
+			get_writeback_data(&val);
+
+			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
+				memcpy(prev_in, vec.ct.val, TDES_BLOCK_SIZE);
+
+			if (j == 0) {
+				memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
+
+				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+					memcpy(vec.pt.val, vec.iv.val,
+							TDES_BLOCK_SIZE);
+					memcpy(vec.iv.val, val.val,
+							TDES_BLOCK_SIZE);
+				} else {
+					memcpy(vec.iv.val, vec.ct.val,
+							TDES_BLOCK_SIZE);
+					memcpy(vec.ct.val, val.val,
+							TDES_BLOCK_SIZE);
+				}
+				continue;
+			}
+
+			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+				memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
+				memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
+			} else {
+				memcpy(vec.iv.val, vec.ct.val, TDES_BLOCK_SIZE);
+				memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
+			}
+
+			if (j == TDES_INTERN_ITER - 1)
+				continue;
+
+			memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
+
+			if (j == TDES_INTERN_ITER - 3)
+				memcpy(prev_prev_out, val.val, TDES_BLOCK_SIZE);
+		}
+
+		info.parse_writeback(&val);
+		fprintf(info.fp_wr, "\n");
+
+		if (i == TDES_EXTERN_ITER - 1)
+			continue;
+
+		/** update key */
+		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
+
+		if (info.interim_info.tdes_data.nb_keys == 0) {
+			if (memcmp(val_key.val, val_key.val + 8, 8) == 0)
+				info.interim_info.tdes_data.nb_keys = 1;
+			else if (memcmp(val_key.val, val_key.val + 16, 8) == 0)
+				info.interim_info.tdes_data.nb_keys = 2;
+			else
+				info.interim_info.tdes_data.nb_keys = 3;
+
+		}
+
+		for (k = 0; k < TDES_BLOCK_SIZE; k++) {
+
+			switch (info.interim_info.tdes_data.nb_keys) {
+			case 3:
+				val_key.val[k] ^= val.val[k];
+				val_key.val[k + 8] ^= prev_out[k];
+				val_key.val[k + 16] ^= prev_prev_out[k];
+				break;
+			case 2:
+				val_key.val[k] ^= val.val[k];
+				val_key.val[k + 8] ^= prev_out[k];
+				val_key.val[k + 16] ^= val.val[k];
+				break;
+			default: /* case 1 */
+				val_key.val[k] ^= val.val[k];
+				val_key.val[k + 8] ^= val.val[k];
+				val_key.val[k + 16] ^= val.val[k];
+				break;
+			}
+
+		}
+
+		for (k = 0; k < 24; k++)
+			val_key.val[k] = (__builtin_popcount(val_key.val[k]) &
+					0x1) ?
+					val_key.val[k] : (val_key.val[k] ^ 0x1);
+
+		if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+			memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
+			memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
+		} else {
+			memcpy(vec.iv.val, prev_out, TDES_BLOCK_SIZE);
+			memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
+		}
+	}
+
+	return 0;
+}
+
+static int
 fips_mct_aes_test(void)
 {
 #define AES_BLOCK_SIZE	16
@@ -758,6 +925,14 @@ init_test_ops(void)
 		test_ops.prepare_xform = prepare_hmac_xform;
 		test_ops.test = fips_generic_test;
 		break;
+	case FIPS_TEST_ALGO_TDES:
+		test_ops.prepare_op = prepare_cipher_op;
+		test_ops.prepare_xform  = prepare_tdes_xform;
+		if (info.interim_info.tdes_data.test_type == TDES_MCT)
+			test_ops.test = fips_mct_tdes_test;
+		else
+			test_ops.test = fips_generic_test;
+		break;
 
 	default:
 		return -1;
diff --git a/examples/cryptodev_fips_validate/meson.build b/examples/cryptodev_fips_validate/meson.build
index 3e06f59..997ee4e 100644
--- a/examples/cryptodev_fips_validate/meson.build
+++ b/examples/cryptodev_fips_validate/meson.build
@@ -11,6 +11,7 @@ allow_experimental_apis = true
 sources = files(
 	'cryptodev_fips_parse_aes.c',
 	'cryptodev_fips_parse_hmac.c',
+	'cryptodev_fips_parse_3des.c',
 	'cryptodev_fips_parse_validate.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v5 5/8] examples/cryptodev_fips_validate: add gcm parser
  2018-10-17 12:49 ` [dpdk-dev] [PATCH v5 " Marko Kovacevic
                     ` (3 preceding siblings ...)
  2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 4/8] examples/cryptodev_fips_validate: add TDES parser and enablement for test types Marko Kovacevic
@ 2018-10-17 12:49   ` Marko Kovacevic
  2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 6/8] examples/cryptodev_fips_validate: add cmac parser and enablement for test types Marko Kovacevic
                     ` (4 subsequent siblings)
  9 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-17 12:49 UTC (permalink / raw)
  To: dev; +Cc: roy.fan.zhang, akhil.goyal, arkadiuszx.kusztal, Marko Kovacevic

Added enablement for GCM parser, to allow the
application to parser the GCM request file and to validate all
tests supported.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 examples/cryptodev_fips_validate/Makefile          |   1 +
 .../cryptodev_fips_parse_gcm.c                     | 125 +++++++++++++++++++++
 .../cryptodev_fips_parse_validate.c                |   5 +
 .../cryptodev_fips_validate.h                      |   4 +
 examples/cryptodev_fips_validate/main.c            | 116 ++++++++++++++++++-
 examples/cryptodev_fips_validate/meson.build       |   1 +
 6 files changed, 251 insertions(+), 1 deletion(-)
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_gcm.c

diff --git a/examples/cryptodev_fips_validate/Makefile b/examples/cryptodev_fips_validate/Makefile
index 2ddf326..f8cfda7 100644
--- a/examples/cryptodev_fips_validate/Makefile
+++ b/examples/cryptodev_fips_validate/Makefile
@@ -8,6 +8,7 @@ APP = fips_validation
 SRCS-y := cryptodev_fips_parse_aes.c
 SRCS-y += cryptodev_fips_parse_hmac.c
 SRCS-y += cryptodev_fips_parse_3des.c
+SRCS-y += cryptodev_fips_parse_gcm.c
 SRCS-y += cryptodev_fips_parse_validate.c
 SRCS-y += main.c
 
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_gcm.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_gcm.c
new file mode 100644
index 0000000..6999dad
--- /dev/null
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_gcm.c
@@ -0,0 +1,125 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+
+#include <rte_cryptodev.h>
+
+#include "cryptodev_fips_validate.h"
+
+#define NEW_LINE_STR	"#"
+#define OP_STR		"GCM "
+
+#define PARAM_PREFIX	"["
+#define KEYLEN_STR	"Keylen = "
+#define IVLEN_STR	"IVlen = "
+#define PTLEN_STR	"PTlen = "
+#define AADLEN_STR	"AADlen = "
+#define TAGLEN_STR	"Taglen = "
+
+#define COUNT_STR	"Count = "
+#define KEY_STR		"Key = "
+#define IV_STR		"IV = "
+#define PT_STR		"PT = "
+#define CT_STR		"CT = "
+#define TAG_STR		"Tag = "
+#define AAD_STR		"AAD = "
+
+#define OP_ENC_STR	"Encrypt"
+#define OP_DEC_STR	"Decrypt"
+
+#define NEG_TEST_STR	"FAIL"
+
+struct fips_test_callback gcm_dec_vectors[] = {
+		{KEY_STR, parse_uint8_known_len_hex_str, &vec.cipher_auth.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.cipher_auth.aad},
+		{TAG_STR, parse_uint8_known_len_hex_str,
+				&vec.cipher_auth.digest},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+struct fips_test_callback gcm_interim_vectors[] = {
+		{KEYLEN_STR, parser_read_uint32_bit_val, &vec.cipher_auth.key},
+		{IVLEN_STR, parser_read_uint32_bit_val, &vec.iv},
+		{PTLEN_STR, parser_read_uint32_bit_val, &vec.pt},
+		{AADLEN_STR, parser_read_uint32_bit_val, &vec.cipher_auth.aad},
+		{TAGLEN_STR, parser_read_uint32_bit_val,
+				&vec.cipher_auth.digest},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback gcm_enc_vectors[] = {
+		{KEY_STR, parse_uint8_known_len_hex_str, &vec.cipher_auth.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.cipher_auth.aad},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+static int
+parse_test_gcm_writeback(struct fips_val *val)
+{
+	struct fips_val tmp_val;
+
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+		fprintf(info.fp_wr, "%s", CT_STR);
+
+		tmp_val.val = val->val;
+		tmp_val.len = vec.pt.len;
+
+		parse_write_hex_str(&tmp_val);
+
+		fprintf(info.fp_wr, "%s", TAG_STR);
+
+		tmp_val.val = val->val + vec.pt.len;
+		tmp_val.len = val->len - vec.pt.len;
+
+		parse_write_hex_str(&tmp_val);
+	} else {
+		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS) {
+			fprintf(info.fp_wr, "%s", PT_STR);
+
+			tmp_val.val = val->val;
+			tmp_val.len = vec.pt.len;
+
+			parse_write_hex_str(&tmp_val);
+		} else
+			fprintf(info.fp_wr, "%s\n", NEG_TEST_STR);
+	}
+
+	return 0;
+}
+
+int
+parse_test_gcm_init(void)
+{
+	char *tmp;
+	uint32_t i;
+
+
+	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;
+			} else if (strstr(line, OP_DEC_STR)) {
+				info.op = FIPS_TEST_DEC_AUTH_VERIF;
+				info.callbacks = gcm_dec_vectors;
+			} else
+				return -EINVAL;
+		}
+	}
+
+	info.interim_callbacks = gcm_interim_vectors;
+	info.parse_writeback = parse_test_gcm_writeback;
+
+	return 0;
+}
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
index bb396e5..d45c88d 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
@@ -109,6 +109,11 @@ fips_test_parse_header(void)
 			ret = parse_test_aes_init();
 			if (ret < 0)
 				return ret;
+		} else if (strstr(info.vec[i], "GCM")) {
+			info.algo = FIPS_TEST_ALGO_AES_GCM;
+			ret = parse_test_gcm_init();
+			if (ret < 0)
+				return ret;
 		} else if (strstr(info.vec[i], "HMAC")) {
 			info.algo = FIPS_TEST_ALGO_HMAC;
 			ret = parse_test_hmac_init();
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
index c9b11dd..685bc0b 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
@@ -24,6 +24,7 @@
 
 enum fips_test_algorithms {
 		FIPS_TEST_ALGO_AES = 0,
+		FIPS_TEST_ALGO_AES_GCM,
 		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_MAX
@@ -172,6 +173,9 @@ int
 parse_test_hmac_init(void);
 
 int
+parse_test_gcm_init(void);
+
+int
 parser_read_uint8_hex(uint8_t *value, const char *p);
 
 int
diff --git a/examples/cryptodev_fips_validate/main.c b/examples/cryptodev_fips_validate/main.c
index 245c40a..93b2420 100644
--- a/examples/cryptodev_fips_validate/main.c
+++ b/examples/cryptodev_fips_validate/main.c
@@ -462,6 +462,70 @@ prepare_auth_op(void)
 }
 
 static int
+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);
+
+	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+	rte_pktmbuf_reset(env.mbuf);
+
+	memcpy(iv, vec.iv.val, vec.iv.len);
+
+	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 (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);
+
+		if (!pt) {
+			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
+					-ENOMEM);
+			return -ENOMEM;
+		}
+
+		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);
+	} 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;
+		}
+
+		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);
+	}
+
+	rte_crypto_op_attach_sym_session(env.op, env.sess);
+}
+
+static int
 prepare_aes_xform(struct rte_crypto_sym_xform *xform)
 {
 	const struct rte_cryptodev_symmetric_capability *cap;
@@ -578,6 +642,52 @@ prepare_hmac_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_gcm_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_aead_xform *aead_xform = &xform->aead;
+
+	xform->type = RTE_CRYPTO_SYM_XFORM_AEAD;
+
+	aead_xform->algo = RTE_CRYPTO_AEAD_AES_GCM;
+	aead_xform->aad_length = vec.aead.aad.len;
+	aead_xform->digest_length = vec.aead.digest.len;
+	aead_xform->iv.offset = IV_OFF;
+	aead_xform->iv.length = vec.iv.len;
+	aead_xform->key.data = vec.aead.key.val;
+	aead_xform->key.length = vec.aead.key.len;
+	aead_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_AEAD_OP_ENCRYPT :
+			RTE_CRYPTO_AEAD_OP_DECRYPT;
+
+	cap_idx.algo.aead = aead_xform->algo;
+	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
+
+	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_aead(cap,
+			aead_xform->key.length,
+			aead_xform->digest_length, aead_xform->aad_length,
+			aead_xform->iv.length) != 0) {
+		RTE_LOG(ERR, USER1,
+			"PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n",
+				info.device_name, aead_xform->key.length,
+				aead_xform->digest_length,
+				aead_xform->aad_length,
+				aead_xform->iv.length);
+		return -EPERM;
+	}
+
+	return 0;
+}
+
 static void
 get_writeback_data(struct fips_val *val)
 {
@@ -933,7 +1043,11 @@ init_test_ops(void)
 		else
 			test_ops.test = fips_generic_test;
 		break;
-
+	case FIPS_TEST_ALGO_AES_GCM:
+		test_ops.prepare_op = prepare_aead_op;
+		test_ops.prepare_xform = prepare_gcm_xform;
+		test_ops.test = fips_generic_test;
+		break;
 	default:
 		return -1;
 	}
diff --git a/examples/cryptodev_fips_validate/meson.build b/examples/cryptodev_fips_validate/meson.build
index 997ee4e..3175993 100644
--- a/examples/cryptodev_fips_validate/meson.build
+++ b/examples/cryptodev_fips_validate/meson.build
@@ -12,6 +12,7 @@ sources = files(
 	'cryptodev_fips_parse_aes.c',
 	'cryptodev_fips_parse_hmac.c',
 	'cryptodev_fips_parse_3des.c',
+	'cryptodev_fips_parse_gcm.c',
 	'cryptodev_fips_parse_validate.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v5 6/8] examples/cryptodev_fips_validate: add cmac parser and enablement for test types
  2018-10-17 12:49 ` [dpdk-dev] [PATCH v5 " Marko Kovacevic
                     ` (4 preceding siblings ...)
  2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 5/8] examples/cryptodev_fips_validate: add gcm parser Marko Kovacevic
@ 2018-10-17 12:49   ` Marko Kovacevic
  2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 7/8] examples/cryptodev_fips_validate: add ccm " Marko Kovacevic
                     ` (3 subsequent siblings)
  9 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-17 12:49 UTC (permalink / raw)
  To: dev; +Cc: roy.fan.zhang, akhil.goyal, arkadiuszx.kusztal, Marko Kovacevic

Added enablement for CMAC parser, to allow the
application to parser the cmac request files and to validate all
test types supported.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 examples/cryptodev_fips_validate/Makefile          |   1 +
 .../cryptodev_fips_parse_cmac.c                    | 116 +++++++++++++++++++++
 .../cryptodev_fips_parse_validate.c                |   5 +
 .../cryptodev_fips_validate.h                      |   4 +
 examples/cryptodev_fips_validate/main.c            |  43 ++++++++
 examples/cryptodev_fips_validate/meson.build       |   1 +
 6 files changed, 170 insertions(+)
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_cmac.c

diff --git a/examples/cryptodev_fips_validate/Makefile b/examples/cryptodev_fips_validate/Makefile
index f8cfda7..09acfd3 100644
--- a/examples/cryptodev_fips_validate/Makefile
+++ b/examples/cryptodev_fips_validate/Makefile
@@ -9,6 +9,7 @@ SRCS-y := cryptodev_fips_parse_aes.c
 SRCS-y += cryptodev_fips_parse_hmac.c
 SRCS-y += cryptodev_fips_parse_3des.c
 SRCS-y += cryptodev_fips_parse_gcm.c
+SRCS-y += cryptodev_fips_parse_cmac.c
 SRCS-y += cryptodev_fips_parse_validate.c
 SRCS-y += main.c
 
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_cmac.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_cmac.c
new file mode 100644
index 0000000..37c6317
--- /dev/null
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_cmac.c
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+#include <rte_string_fns.h>
+
+#include <rte_cryptodev.h>
+
+#include "cryptodev_fips_validate.h"
+
+#define NEW_LINE_STR	"#"
+#define OP_STR		"CMAC"
+
+#define ALGO_STR	"Alg = "
+#define MODE_STR	"Mode = "
+
+#define COUNT_STR	"Count = "
+#define KLEN_STR	"Klen = "
+#define PTLEN_STR	"Mlen = "
+#define TAGLEN_STR	"Tlen = "
+#define KEY_STR		"Key = "
+#define PT_STR		"Msg = "
+#define TAG_STR		"Mac = "
+
+#define GEN_STR		"Generate"
+#define VERIF_STR	"Verify"
+
+#define POS_NEG_STR	"Result = "
+#define PASS_STR	"P"
+#define FAIL_STR	"F"
+
+struct hash_algo_conversion {
+	const char *str;
+	enum fips_test_algorithms algo;
+} cmac_algo[] = {
+		{"AES", FIPS_TEST_ALGO_AES_CMAC},
+};
+
+static int
+parse_test_cmac_writeback(struct fips_val *val)
+{
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+		struct fips_val tmp_val = {val->val + vec.pt.len,
+				vec.cipher_auth.digest.len};
+
+		fprintf(info.fp_wr, "%s", TAG_STR);
+		parse_write_hex_str(&tmp_val);
+	} else {
+		fprintf(info.fp_wr, "%s", POS_NEG_STR);
+
+		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS)
+			fprintf(info.fp_wr, "%s\n", PASS_STR);
+		else if (vec.status == RTE_CRYPTO_OP_STATUS_AUTH_FAILED)
+			fprintf(info.fp_wr, "%s\n", FAIL_STR);
+		else
+			fprintf(info.fp_wr, "Error\n");
+	}
+
+	return 0;
+}
+
+struct fips_test_callback cmac_tests_vectors[] = {
+		{KLEN_STR, parser_read_uint32_val, &vec.cipher_auth.key},
+		{PTLEN_STR, parser_read_uint32_val, &vec.pt},
+		{TAGLEN_STR, parser_read_uint32_val, &vec.cipher_auth.digest},
+		{KEY_STR, parse_uint8_hex_str, &vec.cipher_auth.key},
+		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
+		{TAG_STR, parse_uint8_known_len_hex_str,
+				&vec.cipher_auth.digest},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+int
+parse_test_cmac_init(void)
+{
+	char *tmp;
+	uint32_t i, j;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		char *line = info.vec[i];
+
+		tmp = strstr(line, ALGO_STR);
+		if (!tmp)
+			continue;
+
+		for (j = 0; j < RTE_DIM(cmac_algo); j++) {
+			if (!strstr(line, cmac_algo[j].str))
+				continue;
+
+			info.algo = cmac_algo[j].algo;
+			break;
+		}
+
+		if (j == RTE_DIM(cmac_algo))
+			return -EINVAL;
+
+		tmp = strstr(line, MODE_STR);
+		if (!tmp)
+			return -1;
+
+		if (strstr(tmp, GEN_STR))
+			info.op = FIPS_TEST_ENC_AUTH_GEN;
+		else if (strstr(tmp, VERIF_STR))
+			info.op = FIPS_TEST_DEC_AUTH_VERIF;
+		else
+			return -EINVAL;
+	}
+
+	info.parse_writeback = parse_test_cmac_writeback;
+	info.callbacks = cmac_tests_vectors;
+
+	return 0;
+}
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
index d45c88d..4617c67 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
@@ -114,6 +114,11 @@ fips_test_parse_header(void)
 			ret = parse_test_gcm_init();
 			if (ret < 0)
 				return ret;
+		} else if (strstr(info.vec[i], "CMAC")) {
+			info.algo = FIPS_TEST_ALGO_AES_CMAC;
+			ret = parse_test_cmac_init();
+			if (ret < 0)
+				return 0;
 		} else if (strstr(info.vec[i], "HMAC")) {
 			info.algo = FIPS_TEST_ALGO_HMAC;
 			ret = parse_test_hmac_init();
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
index 685bc0b..7bd1e9a 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
@@ -25,6 +25,7 @@
 enum fips_test_algorithms {
 		FIPS_TEST_ALGO_AES = 0,
 		FIPS_TEST_ALGO_AES_GCM,
+		FIPS_TEST_ALGO_AES_CMAC,
 		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_MAX
@@ -176,6 +177,9 @@ int
 parse_test_gcm_init(void);
 
 int
+parse_test_cmac_init(void);
+
+int
 parser_read_uint8_hex(uint8_t *value, const char *p);
 
 int
diff --git a/examples/cryptodev_fips_validate/main.c b/examples/cryptodev_fips_validate/main.c
index 93b2420..51ee4ad 100644
--- a/examples/cryptodev_fips_validate/main.c
+++ b/examples/cryptodev_fips_validate/main.c
@@ -688,6 +688,44 @@ prepare_gcm_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_cmac_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_CMAC;
+	auth_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_AUTH_OP_GENERATE : RTE_CRYPTO_AUTH_OP_VERIFY;
+	auth_xform->digest_length = vec.cipher_auth.digest.len;
+	auth_xform->key.data = vec.cipher_auth.key.val;
+	auth_xform->key.length = vec.cipher_auth.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 void
 get_writeback_data(struct fips_val *val)
 {
@@ -1048,6 +1086,11 @@ init_test_ops(void)
 		test_ops.prepare_xform = prepare_gcm_xform;
 		test_ops.test = fips_generic_test;
 		break;
+	case FIPS_TEST_ALGO_AES_CMAC:
+		test_ops.prepare_op = prepare_auth_op;
+		test_ops.prepare_xform = prepare_cmac_xform;
+		test_ops.test = fips_generic_test;
+		break;
 	default:
 		return -1;
 	}
diff --git a/examples/cryptodev_fips_validate/meson.build b/examples/cryptodev_fips_validate/meson.build
index 3175993..de6de7b 100644
--- a/examples/cryptodev_fips_validate/meson.build
+++ b/examples/cryptodev_fips_validate/meson.build
@@ -13,6 +13,7 @@ sources = files(
 	'cryptodev_fips_parse_hmac.c',
 	'cryptodev_fips_parse_3des.c',
 	'cryptodev_fips_parse_gcm.c',
+	'cryptodev_fips_parse_cmac.c',
 	'cryptodev_fips_parse_validate.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v5 7/8] examples/cryptodev_fips_validate: add ccm parser and enablement for test types
  2018-10-17 12:49 ` [dpdk-dev] [PATCH v5 " Marko Kovacevic
                     ` (5 preceding siblings ...)
  2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 6/8] examples/cryptodev_fips_validate: add cmac parser and enablement for test types Marko Kovacevic
@ 2018-10-17 12:49   ` Marko Kovacevic
  2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 8/8] doc/guides/sample_app_ug: add guides for fips validation Marko Kovacevic
                     ` (2 subsequent siblings)
  9 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-17 12:49 UTC (permalink / raw)
  To: dev; +Cc: roy.fan.zhang, akhil.goyal, arkadiuszx.kusztal, Marko Kovacevic

Added enablement for CCM parser, to allow the
application to parser the ccm request files and to validate all
test types supported.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 examples/cryptodev_fips_validate/Makefile          |   1 +
 .../cryptodev_fips_parse_ccm.c                     | 272 +++++++++++++++++++++
 .../cryptodev_fips_parse_validate.c                |   5 +
 .../cryptodev_fips_validate.h                      |  22 ++
 examples/cryptodev_fips_validate/main.c            |  56 ++++-
 examples/cryptodev_fips_validate/meson.build       |   1 +
 6 files changed, 356 insertions(+), 1 deletion(-)
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_ccm.c

diff --git a/examples/cryptodev_fips_validate/Makefile b/examples/cryptodev_fips_validate/Makefile
index 09acfd3..c07d35a 100644
--- a/examples/cryptodev_fips_validate/Makefile
+++ b/examples/cryptodev_fips_validate/Makefile
@@ -10,6 +10,7 @@ SRCS-y += cryptodev_fips_parse_hmac.c
 SRCS-y += cryptodev_fips_parse_3des.c
 SRCS-y += cryptodev_fips_parse_gcm.c
 SRCS-y += cryptodev_fips_parse_cmac.c
+SRCS-y += cryptodev_fips_parse_ccm.c
 SRCS-y += cryptodev_fips_parse_validate.c
 SRCS-y += main.c
 
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_ccm.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_ccm.c
new file mode 100644
index 0000000..0fdb75a
--- /dev/null
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_ccm.c
@@ -0,0 +1,272 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <rte_string_fns.h>
+#include <rte_cryptodev.h>
+#include <rte_malloc.h>
+
+#include "cryptodev_fips_validate.h"
+
+#define DVPT_STR	"CCM-DVPT"
+#define VADT_STR	"CCM-VADT"
+#define VPT_STR		"CCM-VPT"
+#define VNT_STR		"CCM-VNT"
+#define VTT_STR		"CCM-VTT"
+
+#define PARAM_PREFIX	"["
+#define ALEN_PREFIX	"Alen = "
+#define PLEN_PREFIX	"Plen = "
+#define IVLEN_PREFIX	"Nlen = "
+#define DIGESTL_PREFIX	"Tlen = "
+
+#define COUNT_STR	"Count = "
+#define KEY_STR		"Key = "
+#define IV_STR		"Nonce = "
+#define PT_STR		"Payload = "
+#define CT_STR		"CT = "
+#define AAD_STR		"Adata = "
+#define POS_NEG_STR	"Result = "
+
+#define POS_KEYWORD	"Pass"
+#define NEG_KEYWORD	"Fail"
+
+static int
+parser_dvpt_interim(const char *key, char *src, struct fips_val *val)
+{
+	char *tmp, c, value[10];
+	char num_pattern[] = "0123456789";
+	int i = 0;
+
+	memset(value, 0, 10);
+
+	tmp = strstr(src, key);
+	if (!tmp)
+		return -1;
+
+	tmp += strlen(key);
+
+	c = tmp[0];
+
+	while (strchr(num_pattern, c) && i < 10) {
+		value[i++] = c;
+		c = tmp[i];
+	}
+
+	return parser_read_uint32_val("", value, val);
+}
+
+static int
+parse_dvpt_ct_hex_str(const char *key, char *src, struct fips_val *val)
+{
+	int ret;
+
+	val->len = vec.pt.len;
+
+	ret = parse_uint8_known_len_hex_str(key, src, val);
+	if (ret < 0)
+		return ret;
+
+	src += strlen(key) + val->len * 2;
+
+	ret = parse_uint8_known_len_hex_str("", src, &vec.aead.digest);
+	if (ret < 0) {
+		rte_free(val->val);
+		memset(val, 0, sizeof(*val));
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+parse_uint8_ccm_aad_str(const char *key, char *src, struct fips_val *val)
+{
+	uint32_t len = val->len, j;
+
+	src += strlen(key);
+
+	/* CCM aad requires 18 bytes padding before the real content */
+	val->val = rte_zmalloc(NULL, len + 18, 0);
+	if (!val->val)
+		return -1;
+
+	for (j = 0; j < len; j++) {
+		char byte[3] = {src[j * 2], src[j * 2 + 1], '\0'};
+
+		if (parser_read_uint8_hex(&val->val[j + 18], byte) < 0) {
+			rte_free(val->val);
+			memset(val, 0, sizeof(*val));
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+struct fips_test_callback ccm_vnt_vec[] = {
+		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
+		{AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad},
+		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vnt_interim_vec[] = {
+		{ALEN_PREFIX, parser_read_uint32_val, &vec.aead.aad},
+		{PLEN_PREFIX, parser_read_uint32_val, &vec.pt},
+		{DIGESTL_PREFIX, parser_read_uint32_val, &vec.aead.digest},
+		{IVLEN_PREFIX, parser_read_uint32_val, &vec.iv},
+		{KEY_STR, parse_uint8_hex_str, &vec.aead.key},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vtt_vec[] = {
+		{AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad},
+		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vtt_interim_vec[] = {
+		{ALEN_PREFIX, parser_read_uint32_val, &vec.aead.aad},
+		{PLEN_PREFIX, parser_read_uint32_val, &vec.pt},
+		{IVLEN_PREFIX, parser_read_uint32_val, &vec.iv},
+		{DIGESTL_PREFIX, parser_read_uint32_val, &vec.aead.digest},
+		{KEY_STR, parse_uint8_hex_str, &vec.aead.key},
+		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vadt_vec[] = {
+		{AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad},
+		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vadt_interim_vec[] = {
+		{PLEN_PREFIX, parser_read_uint32_val, &vec.pt},
+		{IVLEN_PREFIX, parser_read_uint32_val, &vec.iv},
+		{ALEN_PREFIX, parser_read_uint32_val, &vec.aead.aad},
+		{DIGESTL_PREFIX, parser_read_uint32_val, &vec.aead.digest},
+		{KEY_STR, parse_uint8_hex_str, &vec.aead.key},
+		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vpt_vec[] = {
+		{AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad},
+		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vpt_interim_vec[] = {
+		{ALEN_PREFIX, parser_read_uint32_val, &vec.aead.aad},
+		{IVLEN_PREFIX, parser_read_uint32_val, &vec.iv},
+		{DIGESTL_PREFIX, parser_read_uint32_val, &vec.aead.digest},
+		{PLEN_PREFIX, parser_read_uint32_val, &vec.pt},
+		{KEY_STR, parse_uint8_hex_str, &vec.aead.key},
+		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_dvpt_vec[] = {
+		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
+		{AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad},
+		{CT_STR, parse_dvpt_ct_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_dvpt_interim_vec[] = {
+		{ALEN_PREFIX, parser_dvpt_interim, &vec.aead.aad},
+		{PLEN_PREFIX, parser_dvpt_interim, &vec.pt},
+		{IVLEN_PREFIX, parser_dvpt_interim, &vec.iv},
+		{DIGESTL_PREFIX, parser_dvpt_interim, &vec.aead.digest},
+		{KEY_STR, parse_uint8_hex_str, &vec.aead.key},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct ccm_test_types {
+	const char *str;
+	uint32_t type;
+	const struct fips_test_callback *cb;
+	const struct fips_test_callback *cb_interim;
+	enum fips_test_op op;
+} ctt[] = {
+		{DVPT_STR, CCM_DVPT, ccm_dvpt_vec, ccm_dvpt_interim_vec,
+			FIPS_TEST_DEC_AUTH_VERIF},
+		{VPT_STR, CCM_VPT, ccm_vpt_vec, ccm_vpt_interim_vec,
+			FIPS_TEST_ENC_AUTH_GEN},
+		{VADT_STR, CCM_VADT, ccm_vadt_vec, ccm_vadt_interim_vec,
+			FIPS_TEST_ENC_AUTH_GEN},
+		{VNT_STR, CCM_VNT, ccm_vnt_vec, ccm_vnt_interim_vec,
+			FIPS_TEST_ENC_AUTH_GEN},
+		{VTT_STR, CCM_VTT, ccm_vtt_vec, ccm_vtt_interim_vec,
+			FIPS_TEST_ENC_AUTH_GEN},
+};
+
+static int
+parse_test_ccm_writeback(struct fips_val *val)
+{
+	struct fips_val tmp_val;
+
+	switch (info.interim_info.ccm_data.test_type) {
+	case CCM_DVPT:
+		fprintf(info.fp_wr, "%s", POS_NEG_STR);
+		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS) {
+			fprintf(info.fp_wr, "%s\n", POS_KEYWORD);
+			fprintf(info.fp_wr, "%s", PT_STR);
+
+			tmp_val.val = val->val;
+			tmp_val.len = vec.pt.len;
+
+			if (tmp_val.len == 0)
+				fprintf(info.fp_wr, "00\n");
+			else
+				parse_write_hex_str(&tmp_val);
+		} else
+			fprintf(info.fp_wr, "%s\n", NEG_KEYWORD);
+
+		break;
+
+	case CCM_VADT:
+	case CCM_VNT:
+	case CCM_VPT:
+	case CCM_VTT:
+		fprintf(info.fp_wr, "%s", CT_STR);
+
+		parse_write_hex_str(val);
+
+		break;
+
+	}
+
+	return 0;
+}
+
+int
+parse_test_ccm_init(void)
+{
+
+	uint32_t i;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		char *line = info.vec[i];
+		uint32_t j;
+
+		for (j = 0; j < RTE_DIM(ctt); j++)
+			if (strstr(line, ctt[j].str)) {
+				info.interim_info.ccm_data.test_type =
+						ctt[j].type;
+				info.callbacks = ctt[j].cb;
+				info.interim_callbacks = ctt[j].cb_interim;
+				info.op = ctt[j].op;
+				break;
+		}
+	}
+
+	info.parse_writeback = parse_test_ccm_writeback;
+
+	return 0;
+}
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
index 4617c67..47e3732 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
@@ -119,6 +119,11 @@ fips_test_parse_header(void)
 			ret = parse_test_cmac_init();
 			if (ret < 0)
 				return 0;
+		} else if (strstr(info.vec[i], "CCM")) {
+			info.algo = FIPS_TEST_ALGO_AES_CCM;
+			ret = parse_test_ccm_init();
+			if (ret < 0)
+				return 0;
 		} else if (strstr(info.vec[i], "HMAC")) {
 			info.algo = FIPS_TEST_ALGO_HMAC;
 			ret = parse_test_hmac_init();
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
index 7bd1e9a..afa0c0a 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
@@ -26,6 +26,7 @@ enum fips_test_algorithms {
 		FIPS_TEST_ALGO_AES = 0,
 		FIPS_TEST_ALGO_AES_GCM,
 		FIPS_TEST_ALGO_AES_CMAC,
+		FIPS_TEST_ALGO_AES_CCM,
 		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_MAX
@@ -102,6 +103,14 @@ enum fips_tdes_test_types {
 	TDES_MMT /* Multi block Message Test */
 };
 
+enum fips_ccm_test_types {
+	CCM_VADT	= 1, /* Variable Associated Data Test */
+	CCM_VPT,		 /* Variable Payload Test */
+	CCM_VNT,		 /* Variable Nonce Test */
+	CCM_VTT,		 /* Variable Tag Test */
+	CCM_DVPT,	 /*  Decryption-Verification Process Test */
+};
+
 struct aesavs_interim_data {
 	enum fips_aesavs_test_types test_type;
 	uint32_t cipher_algo;
@@ -117,6 +126,15 @@ struct tdes_interim_data {
 	uint32_t nb_keys;
 };
 
+struct ccm_interim_data {
+	enum fips_ccm_test_types test_type;
+	uint32_t aad_len;
+	uint32_t pt_len;
+	uint32_t digest_len;
+	uint32_t key_len;
+	uint32_t iv_len;
+};
+
 struct fips_test_interim_info {
 	FILE *fp_rd;
 	FILE *fp_wr;
@@ -132,6 +150,7 @@ struct fips_test_interim_info {
 		struct aesavs_interim_data aes_data;
 		struct hmac_interim_data hmac_data;
 		struct tdes_interim_data tdes_data;
+		struct ccm_interim_data ccm_data;
 
 	} interim_info;
 
@@ -180,6 +199,9 @@ int
 parse_test_cmac_init(void);
 
 int
+parse_test_ccm_init(void);
+
+int
 parser_read_uint8_hex(uint8_t *value, const char *p);
 
 int
diff --git a/examples/cryptodev_fips_validate/main.c b/examples/cryptodev_fips_validate/main.c
index 51ee4ad..9a08e27 100644
--- a/examples/cryptodev_fips_validate/main.c
+++ b/examples/cryptodev_fips_validate/main.c
@@ -470,7 +470,10 @@ prepare_aead_op(void)
 	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
 	rte_pktmbuf_reset(env.mbuf);
 
-	memcpy(iv, vec.iv.val, vec.iv.len);
+	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);
 
 	sym->m_src = env.mbuf;
 	sym->aead.data.offset = 0;
@@ -726,6 +729,52 @@ prepare_cmac_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_ccm_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_aead_xform *aead_xform = &xform->aead;
+
+	xform->type = RTE_CRYPTO_SYM_XFORM_AEAD;
+
+	aead_xform->algo = RTE_CRYPTO_AEAD_AES_CCM;
+	aead_xform->aad_length = vec.aead.aad.len;
+	aead_xform->digest_length = vec.aead.digest.len;
+	aead_xform->iv.offset = IV_OFF;
+	aead_xform->iv.length = vec.iv.len;
+	aead_xform->key.data = vec.aead.key.val;
+	aead_xform->key.length = vec.aead.key.len;
+	aead_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_AEAD_OP_ENCRYPT :
+			RTE_CRYPTO_AEAD_OP_DECRYPT;
+
+	cap_idx.algo.aead = aead_xform->algo;
+	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
+
+	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_aead(cap,
+			aead_xform->key.length,
+			aead_xform->digest_length, aead_xform->aad_length,
+			aead_xform->iv.length) != 0) {
+		RTE_LOG(ERR, USER1,
+			"PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n",
+				info.device_name, aead_xform->key.length,
+				aead_xform->digest_length,
+				aead_xform->aad_length,
+				aead_xform->iv.length);
+		return -EPERM;
+	}
+
+	return 0;
+}
+
 static void
 get_writeback_data(struct fips_val *val)
 {
@@ -1091,6 +1140,11 @@ init_test_ops(void)
 		test_ops.prepare_xform = prepare_cmac_xform;
 		test_ops.test = fips_generic_test;
 		break;
+	case FIPS_TEST_ALGO_AES_CCM:
+		test_ops.prepare_op = prepare_aead_op;
+		test_ops.prepare_xform = prepare_ccm_xform;
+		test_ops.test = fips_generic_test;
+		break;
 	default:
 		return -1;
 	}
diff --git a/examples/cryptodev_fips_validate/meson.build b/examples/cryptodev_fips_validate/meson.build
index de6de7b..fd83d1a 100644
--- a/examples/cryptodev_fips_validate/meson.build
+++ b/examples/cryptodev_fips_validate/meson.build
@@ -14,6 +14,7 @@ sources = files(
 	'cryptodev_fips_parse_3des.c',
 	'cryptodev_fips_parse_gcm.c',
 	'cryptodev_fips_parse_cmac.c',
+	'cryptodev_fips_parse_ccm.c',
 	'cryptodev_fips_parse_validate.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v5 8/8] doc/guides/sample_app_ug: add guides for fips validation
  2018-10-17 12:49 ` [dpdk-dev] [PATCH v5 " Marko Kovacevic
                     ` (6 preceding siblings ...)
  2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 7/8] examples/cryptodev_fips_validate: add ccm " Marko Kovacevic
@ 2018-10-17 12:49   ` Marko Kovacevic
  2018-10-24 12:51     ` Akhil Goyal
  2018-10-24 11:42   ` [dpdk-dev] [PATCH v5 0/8] FIPS validation capability Akhil Goyal
  2018-10-26 11:07   ` [dpdk-dev] [PATCH v6 " Marko Kovacevic
  9 siblings, 1 reply; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-17 12:49 UTC (permalink / raw)
  To: dev; +Cc: roy.fan.zhang, akhil.goyal, arkadiuszx.kusztal, Marko Kovacevic

Document explains how to run the fips sample app
and instructions users need to parser all the request
files and generate the response files.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 MAINTAINERS                                  |   4 +
 doc/guides/rel_notes/release_18_11.rst       |   6 ++
 doc/guides/sample_app_ug/fips_validation.rst | 119 +++++++++++++++++++++++++++
 doc/guides/sample_app_ug/index.rst           |   1 +
 4 files changed, 130 insertions(+)
 create mode 100644 doc/guides/sample_app_ug/fips_validation.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 5d73756..31c9c65 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1314,3 +1314,7 @@ F: examples/tep_termination/
 F: examples/vmdq/
 F: examples/vmdq_dcb/
 F: doc/guides/sample_app_ug/vmdq_dcb_forwarding.rst
+
+M: Marko Kovacevic <marko.kovacevic@intel.com>
+F: examples/cryptodev_fips_validate
+F: doc/guides/sample_app_ug/fips_validation.rst
diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index 436b20e..83ad92e 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -54,6 +54,12 @@ New Features
      Also, make sure to start the actual text at the margin.
      =========================================================
 
+* **Added Cryptodev Fips Validation Example Application.**
+
+  Added an example application to parse and perform symmetric cryptography
+  computation to the NIST Cryptographic Algorithm Validation Program (CAVP)
+  test vectors.
+
 * **Added support for using externally allocated memory in DPDK.**
 
   DPDK has gained support for creating new ``rte_malloc`` heaps referencing
diff --git a/doc/guides/sample_app_ug/fips_validation.rst b/doc/guides/sample_app_ug/fips_validation.rst
new file mode 100644
index 0000000..9e0db23
--- /dev/null
+++ b/doc/guides/sample_app_ug/fips_validation.rst
@@ -0,0 +1,119 @@
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(c) 2018 Intel Corporation.
+
+Federal Information Processing Standards (FIPS) CryptoDev Validation
+====================================================================
+
+Overview
+--------
+
+Federal Information Processing Standards (FIPS) are publicly announced standards
+developed by the United States federal government for use in computer systems by
+non-military government agencies and government contractors.
+
+This application is used to parse and perform symmetric cryptography
+computation to the NIST Cryptographic Algorithm Validation Program (CAVP) test
+vectors.
+
+For an algorithm implementation to be listed on a cryptographic module
+validation certificate as an Approved security function, the algorithm
+implementation must meet all the requirements of FIPS 140-2 and must
+successfully complete the cryptographic algorithm validation process.
+
+Limitations
+-----------
+
+* Only NIST CAVP request files are parsed by this application.
+* The version of request file supported is ``CAVS 21.0``
+* If the header comment in a ``.req`` file does not contain a Algo tag
+  i.e ``AES,TDES,GCM`` you need to manually add it into the head comment for
+  example::
+
+      # VARIABLE KEY - KAT for CBC / # TDES VARIABLE KEY - KAT for CBC
+
+* The application does not supply the test vectors. The user is expected to
+  obtain the test vector files from `NIST
+  <https://csrc.nist.gov/projects/cryptographic-algorithm-validation-
+  program/block-ciphers>`_ website. To obtain the ``.req`` files you need to
+  email a person from the NIST webiste and pay for the ``.req`` files.
+  The ``.rsp`` files from the site can be used to validate and compare with
+  the ``.rsp`` files created by the FIPS application.
+
+* Supported test vectors
+    * AES-CBC (128,192,256) - GFSbox, KeySbox, MCT, MMT
+    * AES-GCM (128,192,256) - EncryptExtIV, Decrypt
+    * AES-CCM (128) - VADT, VNT, VPT, VTT, DVPT
+    * AES-CMAC (128) - Generate, Verify
+    * HMAC (SHA1, SHA224, SHA256, SHA384, SHA512)
+    * TDES-CBC (1 Key, 2 Keys, 3 Keys) - MMT, Monte, Permop, Subkey, Varkey,
+      VarText
+
+Compiling the Application
+-------------------------
+
+* Compile Application
+
+    .. code-block:: console
+
+         make -C examples/cryptodev_fips_validate
+
+*  Run ``dos2unix`` on the request files
+
+    .. code-block:: console
+
+         dos2unix AES/req/*
+         dos2unix AES_GCM/req/*
+         dos2unix CCM/req/*
+         dos2unix CMAC/req/*
+         dos2unix HMAC/req/*
+         dos2unix TDES/req/*
+
+Running the Application
+-----------------------
+
+The application requires a number of command line options:
+
+    .. code-block:: console
+
+         ./cryptodev_fips_validate_app [EAL options]
+         -- --req-file FILE_PATH/FOLDER_PATH
+         --rsp-file FILE_PATH/FOLDER_PATH
+         [--cryptodev DEVICE_NAME] [--cryptodev-id ID] [--path-is-folder]
+
+where,
+  * req-file: The path of the request file or folder, separated by
+    ``path-is-folder`` option.
+
+  * rsp-file: The path that the response file or folder is stored. separated by
+    ``path-is-folder`` option.
+
+  * cryptodev: The name of the target DPDK Crypto device to be validated.
+
+  * cryptodev-id: The id of the target DPDK Crypto device to be validated.
+
+  * path-is-folder: If presented the application expects req-file and rsp-file
+    are folder paths.
+
+.. note::
+
+    The .req file is optional and the application can be run without it, but
+    .req files are the only ones that will be parsed by the application.
+
+To run the application in linuxapp environment to test one AES FIPS test data
+file for crypto_aesni_mb PMD, issue the command:
+
+.. code-block:: console
+
+    $ ./cryptodev_fips_validate_app --vdev crypto_aesni_mb --
+    --req-file /PATH/TO/REQUEST/FILE.req --rsp-file ./PATH/TO/RESPONSE/FILE.rsp
+    --cryptodev crypto_aesni_mb
+
+To run the application in linuxapp environment to test all AES-GCM FIPS test
+data files in one folder for crypto_aesni_gcm PMD, issue the command:
+
+.. code-block:: console
+
+    $ ./cryptodev_fips_validate_app --vdev crypto_aesni_gcm0 --
+    --req-file /PATH/TO/REQUEST/FILE/FOLDER/
+    --rsp-file ./PATH/TO/RESPONSE/FILE/FOLDER/
+    --cryptodev-id 0 --path-is-folder
diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst
index 74b12af..65c12d9 100644
--- a/doc/guides/sample_app_ug/index.rst
+++ b/doc/guides/sample_app_ug/index.rst
@@ -57,6 +57,7 @@ Sample Applications User Guides
     performance_thread
     ipsec_secgw
     bbdev_app
+    fips_validation
 
 **Figures**
 
-- 
2.9.5

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

* Re: [dpdk-dev] [PATCH v5 0/8] FIPS validation capability
  2018-10-17 12:49 ` [dpdk-dev] [PATCH v5 " Marko Kovacevic
                     ` (7 preceding siblings ...)
  2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 8/8] doc/guides/sample_app_ug: add guides for fips validation Marko Kovacevic
@ 2018-10-24 11:42   ` Akhil Goyal
  2018-10-26 11:07   ` [dpdk-dev] [PATCH v6 " Marko Kovacevic
  9 siblings, 0 replies; 52+ messages in thread
From: Akhil Goyal @ 2018-10-24 11:42 UTC (permalink / raw)
  To: Marko Kovacevic, dev; +Cc: roy.fan.zhang, arkadiuszx.kusztal

Hi Marko,

On 10/17/2018 6:19 PM, Marko Kovacevic wrote:
> This sample application is made for the purpose so that users of DPDK
> who wish to get FIPS certification for their platforms, this sample app enables
> users to parse test vectors that is gotten from NIST and be able to get
> a generated response file which they can then verify and be sure their
> system will pass FIPS certification.
>
>
> Marko Kovacevic (8):
> v5:
>    - Changed patch titles
patch titles are still not correct

>    - Added MAINTAINERS File
>    - Removed bus_pci Dependency
>    - Updated documentation
>    - Changed app name
I do not see app name changed? Also there is mismatch in the file name 
for doc(.rst file and app name).
I can see that in fips_validation.rst, cryptodev_fips_validate_app is used.
The app name looks pretty long,  I suggested for a shorter name like 
fips_validation
> v4:
> - Added Limitation
> - Changed TDES BLOCK SIZE from 16 -> 8
>    as DES block size is 64bits (main.c)
> v3:
> - Fixed a no-testing bug
> - Fixed some code style issue
>
> v2:
> - Refactor the code.
> - Move the code from test to sample applcation
>
>    examples/cryptodev_fips_validate: add fips validation into examples
examples/fips_validation: add cryptodev fips compliant application
>    examples/cryptodev_fips_validate: add aes parser and enablement for
>      test types
should not this be only examples/fips_validation: support AES parsing
>    examples/cryptodev_fips_validate: add hmac parser
examples/fips_validation: support HMAC parsing
>    examples/cryptodev_fips_validate: add TDES parser and enablement for
>      test types
same for this one -- examples/fips_validation: support TDES parsing
>    examples/cryptodev_fips_validate: add gcm parser
examples/cryptodev_fips_validate: support GCM parsing
>    examples/cryptodev_fips_validate: add cmac parser and enablement for
>      test types
examples/fips_validation: support CMAC parsing
>    examples/cryptodev_fips_validate: add ccm parser and enablement for
>      test types
examples/fips_validation: support CCM parsing
>    doc/guides/sample_app_ug: add guides for fips validation
doc: add fips validation application guide
>
>   MAINTAINERS                                        |    4 +
MAINTAINERS changes shall be split in 2 patches. for 
examples/fips_validation add in 1/8 and for rst file 8/8
>   doc/guides/rel_notes/release_18_11.rst             |    6 +
>   doc/guides/sample_app_ug/fips_validation.rst       |  119 ++
>   doc/guides/sample_app_ug/index.rst                 |    1 +
>   examples/cryptodev_fips_validate/Makefile          |   75 ++
>   .../cryptodev_fips_parse_3des.c                    |  259 +++++
>   .../cryptodev_fips_parse_aes.c                     |  188 +++
>   .../cryptodev_fips_parse_ccm.c                     |  272 +++++
>   .../cryptodev_fips_parse_cmac.c                    |  116 ++
>   .../cryptodev_fips_parse_gcm.c                     |  125 ++
>   .../cryptodev_fips_parse_hmac.c                    |  105 ++
>   .../cryptodev_fips_parse_validate.c                |  593 ++++++++++
>   .../cryptodev_fips_validate.h                      |  234 ++++
>   examples/cryptodev_fips_validate/main.c            | 1221 ++++++++++++++++++++
>   examples/cryptodev_fips_validate/meson.build       |   20 +
>   15 files changed, 3338 insertions(+)
>   create mode 100644 doc/guides/sample_app_ug/fips_validation.rst
>   create mode 100644 examples/cryptodev_fips_validate/Makefile
>   create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c
>   create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c
>   create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_ccm.c
>   create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_cmac.c
>   create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_gcm.c
>   create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_hmac.c
>   create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
>   create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_validate.h
>   create mode 100644 examples/cryptodev_fips_validate/main.c
>   create mode 100644 examples/cryptodev_fips_validate/meson.build
>


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

* Re: [dpdk-dev] [PATCH v5 1/8] examples/cryptodev_fips_validate: add fips validation into examples
  2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 1/8] examples/cryptodev_fips_validate: add fips validation into examples Marko Kovacevic
@ 2018-10-24 12:13     ` Akhil Goyal
  2018-10-24 14:17       ` Marko Kovacevic
  0 siblings, 1 reply; 52+ messages in thread
From: Akhil Goyal @ 2018-10-24 12:13 UTC (permalink / raw)
  To: Marko Kovacevic, dev; +Cc: roy.fan.zhang, arkadiuszx.kusztal



On 10/17/2018 6:19 PM, Marko Kovacevic wrote:
> Added FIPS application into the examples to allow
> users to use a simple sample app to validate
> their systems and be able to get FIPS certification.
>
> Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
> Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
> Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
> ---
>   examples/cryptodev_fips_validate/Makefile          |  69 +++
>   .../cryptodev_fips_parse_validate.c                | 562 +++++++++++++++++++++
>   .../cryptodev_fips_validate.h                      | 150 ++++++
>   examples/cryptodev_fips_validate/main.c            | 388 ++++++++++++++
>   examples/cryptodev_fips_validate/meson.build       |  14 +
>   5 files changed, 1183 insertions(+)
>   create mode 100644 examples/cryptodev_fips_validate/Makefile
>   create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
>   create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_validate.h
>   create mode 100644 examples/cryptodev_fips_validate/main.c
>   create mode 100644 examples/cryptodev_fips_validate/meson.build
>
> diff --git a/examples/cryptodev_fips_validate/Makefile b/examples/cryptodev_fips_validate/Makefile
> new file mode 100644
> index 0000000..7f0e603
> --- /dev/null
> +++ b/examples/cryptodev_fips_validate/Makefile
> @@ -0,0 +1,69 @@
> +# SPDX-License-Identifier: BSD-3-Clause
> +# Copyright(c) 2010-2014 Intel Corporation
I believe this is a copy paste error, it should be 2018
> +
> +# binary name
> +APP = fips_validation
> +
> +# all source are stored in SRCS-y
> +SRCS-y += cryptodev_fips_parse_validate.c
> +SRCS-y += main.c
> +
> +# Build using pkg-config variables if possible
> +$(shell pkg-config --exists libdpdk)
> +ifeq ($(.SHELLSTATUS),0)
> +
> +all: shared
> +.PHONY: shared static
> +shared: build/$(APP)-shared
> +	ln -sf $(APP)-shared build/$(APP)
> +static: build/$(APP)-static
> +	ln -sf $(APP)-static build/$(APP)
> +
> +PC_FILE := $(shell pkg-config --path libdpdk)
> +CFLAGS += -O3 $(shell pkg-config --cflags libdpdk)
> +LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk)
> +LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk)
> +
> +build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
> +	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
> +
> +build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build
> +	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC)
> +
> +build:
> +	@mkdir -p $@
> +
> +.PHONY: clean
> +clean:
> +	rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared
> +	rmdir --ignore-fail-on-non-empty build
> +
> +else
> +
> +ifeq ($(RTE_SDK),)
> +$(error "Please define RTE_SDK environment variable")
> +endif
> +
> +# Default target, can be overridden by command line or environment
> +RTE_TARGET ?= x86_64-native-linuxapp-gcc
> +
> +INC += $(sort $(wildcard *.h))
> +
> +include $(RTE_SDK)/mk/rte.vars.mk
> +
> +CFLAGS += $(WERROR_FLAGS)
> +
> +# workaround for a gcc bug with noreturn attribute
> +# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603
> +ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
> +CFLAGS_main.o += -Wno-return-type
> +endif
> +
> +CFLAGS += -DALLOW_EXPERIMENTAL_API
> +CFLAGS += -I$(SRCDIR)
> +CFLAGS += -O3
> +CFLAGS += $(WERROR_FLAGS)
> +
> +include $(RTE_SDK)/mk/rte.extapp.mk
> +
> +endif
> diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
> new file mode 100644
> index 0000000..aec5bb9
> --- /dev/null
> +++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
> @@ -0,0 +1,562 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2018 Intel Corporation
> + */
> +
> +#include <stdio.h>
> +#include <string.h>
> +
> +#include <rte_string_fns.h>
> +#include <rte_cryptodev.h>
> +#include <rte_malloc.h>
> +
> +#include "cryptodev_fips_validate.h"
> +
> +#define skip_white_spaces(pos)			\
> +({						\
> +	__typeof__(pos) _p = (pos);		\
> +	for ( ; isspace(*_p); _p++)		\
> +		;				\
> +	_p;					\
> +})
> +
> +static int
> +get_file_line(void)
> +{
> +	FILE *fp = info.fp_rd;
> +	char *line = info.one_line_text;
> +	char c;
> +	uint32_t loc = 0;
> +
> +	memset(line, 0, MAX_LINE_CHAR);
> +	while ((c = fgetc(fp)) != EOF) {
> +		if (loc >= MAX_LINE_CHAR - 1)
> +			return -ENOMEM;
> +		if (c == '\n')
> +			return 0;
> +		line[loc++] = c;
> +	}
> +
> +	if (c == EOF)
> +		return -EOF;
> +
> +	return 0;
> +}
> +
> +int
> +fips_test_fetch_one_block(void)
> +{
> +	size_t size;
> +	int ret = 0;
> +	uint32_t i;
> +
> +	for (i = 0; i < info.nb_vec_lines; i++) {
> +		free(info.vec[i]);
> +		info.vec[i] = NULL;
> +	}
> +
> +	i = 0;
> +	do {
> +		if (i >= MAX_LINE_PER_VECTOR) {
> +			ret = -ENOMEM;
> +			goto error_exit;
> +		}
> +
> +		ret = get_file_line();
> +		size = strlen(info.one_line_text);
> +		if (size == 0)
> +			break;
> +
> +		info.vec[i] = calloc(1, size + 5);
> +		if (info.vec[i] == NULL)
> +			goto error_exit;
> +
> +		strlcpy(info.vec[i], info.one_line_text, size + 1);
> +		i++;
> +	} while (ret == 0);
> +
> +	info.nb_vec_lines = i;
> +
> +	return ret;
> +
> +error_exit:
> +	for (i = 0; i < MAX_LINE_PER_VECTOR; i++)
> +		if (info.vec[i] != NULL) {
> +			free(info.vec[i]);
> +			info.vec[i] = NULL;
> +		}
> +
> +	info.nb_vec_lines = 0;
> +
> +	return -ENOMEM;
> +}
> +
> +static int
> +fips_test_parse_header(void)
> +{
> +	uint32_t i;
> +	char *tmp;
> +	int ret;
> +	time_t t = time(NULL);
> +	struct tm *tm_now = localtime(&t);
> +
> +	ret = fips_test_fetch_one_block();
> +	if (ret < 0)
> +		return ret;
> +
> +	for (i = 0; i < info.nb_vec_lines; i++) {
> +
> +		tmp = strstr(info.vec[i], "# Config info for ");
> +		if (tmp != NULL) {
> +			fprintf(info.fp_wr, "%s%s\n", "# Config info for DPDK Cryptodev ",
> +					info.device_name);
> +			continue;
> +		}
> +
> +		tmp = strstr(info.vec[i], "#  HMAC information for ");
> +		if (tmp != NULL) {
> +			fprintf(info.fp_wr, "%s%s\n", "#  HMAC information for "
> +				"DPDK Cryptodev ",
> +				info.device_name);
> +			continue;
> +		}
> +
> +		tmp = strstr(info.vec[i], "# Config Info for : ");
> +		if (tmp != NULL) {
> +
> +			fprintf(info.fp_wr, "%s%s\n", "# Config Info for DPDK Cryptodev : ",
> +					info.device_name);
> +			continue;
> +		}
> +
> +		tmp = strstr(info.vec[i], "# information for ");
> +		if (tmp != NULL) {
> +
> +			char tmp_output[128] = {0};
> +
> +			strlcpy(tmp_output, info.vec[i], tmp - info.vec[i] + 1);
> +
> +			fprintf(info.fp_wr, "%s%s%s\n", tmp_output,
> +					"information for DPDK Cryptodev ",
> +					info.device_name);
> +			continue;
> +		}
> +
> +		tmp = strstr(info.vec[i], " test information for ");
> +		if (tmp != NULL) {
> +			char tmp_output[128] = {0};
> +
> +			strlcpy(tmp_output, info.vec[i], tmp - info.vec[i] + 1);
> +
> +			fprintf(info.fp_wr, "%s%s%s\n", tmp_output,
> +					"test information for DPDK Cryptodev ",
> +					info.device_name);
> +			continue;
> +		}
> +
> +		if (i == info.nb_vec_lines - 1) {
> +			/** update the time as current time, write to file */
> +			fprintf(info.fp_wr, "%s%s\n", "# Generated on ",
> +					asctime(tm_now));
> +			continue;
> +		}
> +
> +		/* to this point, no field need to update,
> +		 *  only copy to rsp file
> +		 */
> +		fprintf(info.fp_wr, "%s\n", info.vec[i]);
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +parse_file_type(const char *path)
> +{
> +	const char *tmp = path + strlen(path) - 3;
> +
> +	if (strstr(tmp, REQ_FILE_PERFIX))
> +		info.file_type = FIPS_TYPE_REQ;
> +	else if (strstr(tmp, RSP_FILE_PERFIX))
> +		info.file_type = FIPS_TYPE_RSP;
> +	else if (strstr(path, FAX_FILE_PERFIX))
> +		info.file_type = FIPS_TYPE_FAX;
> +	else
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +int
> +fips_test_init(const char *req_file_path, const char *rsp_file_path,
> +		const char *device_name)
> +{
> +	if (strcmp(req_file_path, rsp_file_path) == 0) {
> +		RTE_LOG(ERR, USER1, "File paths cannot be the same\n");
> +		return -EINVAL;
> +	}
> +
> +	fips_test_clear();
> +
> +	info.algo = FIPS_TEST_ALGO_MAX;
> +	if (parse_file_type(req_file_path) < 0) {
> +		RTE_LOG(ERR, USER1, "File %s type not supported\n",
> +				req_file_path);
> +		return -EINVAL;
> +	}
> +
> +	info.fp_rd = fopen(req_file_path, "r");
> +	if (!info.fp_rd) {
> +		RTE_LOG(ERR, USER1, "Cannot open file %s\n", req_file_path);
> +		return -EINVAL;
> +	}
> +
> +	info.fp_wr = fopen(rsp_file_path, "w");
> +	if (!info.fp_wr) {
> +		RTE_LOG(ERR, USER1, "Cannot open file %s\n", rsp_file_path);
> +		return -EINVAL;
> +	}
> +
> +	info.one_line_text = calloc(1, MAX_LINE_CHAR);
> +	if (!info.one_line_text) {
> +		RTE_LOG(ERR, USER1, "Insufficient memory\n");
> +		return -ENOMEM;
> +	}
> +
> +	strlcpy(info.device_name, device_name, sizeof(info.device_name));
> +
> +	if (fips_test_parse_header() < 0) {
> +		RTE_LOG(ERR, USER1, "Failed parsing header\n");
> +		return -1;
> +	}
memory leak for calloc done above in case of error.
Also there is no fclose in case of errors.
> +
> +	return 0;
> +}
> +
> +void
> +fips_test_clear(void)
> +{
> +	if (info.fp_rd)
> +		fclose(info.fp_rd);
> +	if (info.fp_wr)
> +		fclose(info.fp_wr);
> +	if (info.one_line_text)
> +		free(info.one_line_text);
> +	if (info.nb_vec_lines) {
> +		uint32_t i;
> +
> +		for (i = 0; i < info.nb_vec_lines; i++)
> +			free(info.vec[i]);
> +	}
> +
> +	memset(&info, 0, sizeof(info));
> +}
> +
> +int
> +fips_test_parse_one_case(void)
> +{
> +	uint32_t i, j = 0;
> +	uint32_t is_interim = 0;
> +	int ret;
> +
> +	if (info.interim_callbacks) {
> +		for (i = 0; i < info.nb_vec_lines; i++) {
> +			for (j = 0; info.interim_callbacks[j].key != NULL; j++)
> +				if (strstr(info.vec[i],
> +					info.interim_callbacks[j].key)) {
it looks interim_callback is a single structure and there is no need for 
treating as an array.
> +					is_interim = 1;
> +
> +					ret = info.interim_callbacks[j].cb(
> +						info.interim_callbacks[j].key,
> +						info.vec[i],
> +						info.interim_callbacks[j].val);
> +					if (ret < 0)
> +						return ret;
> +				}
> +		}
> +	}
> +
> +	if (is_interim) {
> +		for (i = 0; i < info.nb_vec_lines; i++)
> +			fprintf(info.fp_wr, "%s\n", info.vec[i]);
> +		fprintf(info.fp_wr, "\n");
> +		return 1;
> +	}
> +
> +	for (i = 0; i < info.nb_vec_lines; i++) {
> +		for (j = 0; info.callbacks[j].key != NULL; j++)
> +			if (strstr(info.vec[i], info.callbacks[j].key)) {
> +				ret = info.callbacks[j].cb(
> +					info.callbacks[j].key,
> +					info.vec[i], info.callbacks[j].val);
> +				if (ret < 0)
> +					return ret;
> +				break;
> +			}
> +	}
> +
> +	return 0;
> +}
> +
> +void
> +fips_test_write_one_case(void)
> +{
> +	uint32_t i;
> +
> +	for (i = 0; i < info.nb_vec_lines; i++)
> +		fprintf(info.fp_wr, "%s\n", info.vec[i]);
> +}
> +
> +static int
> +parser_read_uint64_hex(uint64_t *value, const char *p)
> +{
> +	char *next;
> +	uint64_t val;
> +
> +	p = skip_white_spaces(p);
> +
> +	val = strtoul(p, &next, 16);
> +	if (p == next)
> +		return -EINVAL;
> +
> +	p = skip_white_spaces(next);
> +	if (*p != '\0')
> +		return -EINVAL;
> +
> +	*value = val;
> +	return 0;
> +}
> +
> +int
> +parser_read_uint8_hex(uint8_t *value, const char *p)
> +{
> +	uint64_t val = 0;
> +	int ret = parser_read_uint64_hex(&val, p);
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	if (val > UINT8_MAX)
> +		return -ERANGE;
> +
> +	*value = val;
> +	return 0;
> +}
> +
> +int
> +parse_uint8_known_len_hex_str(const char *key, char *src, struct fips_val *val)
> +{
> +	struct fips_val tmp_val = {0};
> +	uint32_t len = val->len;
> +	int ret;
> +
> +	if (len == 0) {
> +		if (val->val != NULL) {
> +			rte_free(val->val);
> +			val->val = NULL;
> +		}
> +
> +		return 0;
> +	}
> +
> +	ret = parse_uint8_hex_str(key, src, &tmp_val);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (tmp_val.len == val->len) {
> +		val->val = tmp_val.val;
> +		return 0;
> +	}
> +
> +	if (tmp_val.len < val->len) {
> +		rte_free(tmp_val.val);
> +		return -EINVAL;
> +	}
> +
> +	val->val = rte_zmalloc(NULL, val->len, 0);
> +	if (!val->val) {
> +		rte_free(tmp_val.val);
> +		memset(val, 0, sizeof(*val));
> +		return -ENOMEM;
> +	}
> +
> +	memcpy(val->val, tmp_val.val, val->len);
> +	rte_free(tmp_val.val);
> +
> +	return 0;
> +}
> +
> +int
> +parse_uint8_hex_str(const char *key, char *src, struct fips_val *val)
> +{
> +	uint32_t len, j;
> +
> +	src += strlen(key);
> +
> +	len = strlen(src) / 2;
> +
> +	if (val->val) {
> +		rte_free(val->val);
> +		val->val = NULL;
> +	}
> +
> +	val->val = rte_zmalloc(NULL, len, 0);
> +	if (!val->val)
> +		return -1;
should be -ENOMEM
> +
> +	for (j = 0; j < len; j++) {
> +		char byte[3] = {src[j * 2], src[j * 2 + 1], '\0'};
> +
> +		if (parser_read_uint8_hex(&val->val[j], byte) < 0) {
> +			rte_free(val->val);
> +			memset(val, 0, sizeof(*val));
> +			return -EINVAL;
> +		}
> +	}
> +
> +	val->len = len;
> +
> +	return 0;
> +}
> +
> +int
> +parser_read_uint32_val(const char *key, char *src, struct fips_val *val)
> +{
> +	char *data = src + strlen(key);
> +	size_t data_len = strlen(data);
> +	int ret;
> +
> +	if (data[data_len - 1] == ']') {
> +		char *tmp_data = calloc(1, data_len + 1);
> +
> +		if (tmp_data == NULL)
> +			return -ENOMEM;
> +
> +		strlcpy(tmp_data, data, data_len);
> +
> +		ret = parser_read_uint32(&val->len, tmp_data);
> +
> +		free(tmp_data);
> +	} else
> +		ret = parser_read_uint32(&val->len, data);
> +
> +	return ret;
> +}
> +
> +int
> +parser_read_uint32_bit_val(const char *key, char *src, struct fips_val *val)
> +{
> +	int ret;
> +
> +	ret = parser_read_uint32_val(key, src, val);
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	val->len /= 8;
> +
> +	return 0;
> +}
> +
> +int
> +writeback_hex_str(const char *key, char *dst, struct fips_val *val)
> +{
> +	char *str = dst;
> +	uint32_t len;
> +
> +	str += strlen(key);
> +
> +	for (len = 0; len < val->len; len++)
> +		snprintf(str + len * 2, 255, "%02x", val->val[len]);
> +
> +	return 0;
> +}
> +
> +static int
> +parser_read_uint64(uint64_t *value, const char *p)
> +{
> +	char *next;
> +	uint64_t val;
> +
> +	p = skip_white_spaces(p);
> +	if (!isdigit(*p))
> +		return -EINVAL;
> +
> +	val = strtoul(p, &next, 10);
> +	if (p == next)
> +		return -EINVAL;
> +
> +	p = next;
> +	switch (*p) {
> +	case 'T':
> +		val *= 1024ULL;
> +		/* fall through */
> +	case 'G':
> +		val *= 1024ULL;
> +		/* fall through */
> +	case 'M':
> +		val *= 1024ULL;
> +		/* fall through */
> +	case 'k':
> +	case 'K':
> +		val *= 1024ULL;
> +		p++;
> +		break;
> +	}
> +
> +	p = skip_white_spaces(p);
> +	if (*p != '\0')
> +		return -EINVAL;
> +
> +	*value = val;
> +	return 0;
> +}
> +
> +int
> +parser_read_uint32(uint32_t *value, char *p)
> +{
> +	uint64_t val = 0;
> +	int ret = parser_read_uint64(&val, p);
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	if (val > UINT32_MAX)
> +		return -EINVAL;
> +
> +	*value = val;
> +	return 0;
> +}
> +
> +void
> +parse_write_hex_str(struct fips_val *src)
> +{
> +	writeback_hex_str("", info.one_line_text, src);
> +
> +	fprintf(info.fp_wr, "%s\n", info.one_line_text);
> +}
> +
> +int
> +update_info_vec(uint32_t count)
> +{
> +	const struct fips_test_callback *cb;
> +	uint32_t i, j;
> +
> +	if (!info.writeback_callbacks)
> +		return -1;
> +
> +	cb = &info.writeback_callbacks[0];
> +
> +	snprintf(info.vec[0], strlen(info.vec[0]) + 4, "%s%u", cb->key, count);
> +
> +	for (i = 1; i < info.nb_vec_lines; i++) {
> +		for (j = 1; info.writeback_callbacks[j].key != NULL; j++) {
> +			cb = &info.writeback_callbacks[j];
> +			if (strstr(info.vec[i], cb->key)) {
> +				cb->cb(cb->key, info.vec[i], cb->val);
> +				break;
> +			}
> +		}
> +	}
> +
> +	return 0;
> +}
> diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
> new file mode 100644
> index 0000000..beb6bed
> --- /dev/null
> +++ b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
> @@ -0,0 +1,150 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2018 Intel Corporation
> + */
> +
> +#ifndef _CRYPTODEV_NIST_FIPS_PARSER_H_
> +#define _CRYPTODEV_NIST_FIPS_PARSER_H_
> +
> +#define FIPS_PARSE_ERR(fmt, args)					\
> +	RTE_LOG(ERR, USER1, "FIPS parse error" ## fmt ## "\n", ## args)
> +
> +#define ERR_MSG_SIZE		128
> +#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 MAX_STRING_SIZE		64
> +
> +#define POSITIVE_TEST		0
> +#define NEGATIVE_TEST		-1
> +
> +#define REQ_FILE_PERFIX		"req"
> +#define RSP_FILE_PERFIX		"rsp"
> +#define FAX_FILE_PERFIX		"fax"
> +
> +enum fips_test_algorithms {
> +		FIPS_TEST_ALGO_MAX
> +};
> +
> +enum file_types {
> +	FIPS_TYPE_REQ = 1,
> +	FIPS_TYPE_FAX,
> +	FIPS_TYPE_RSP
> +};
> +
> +enum fips_test_op {
> +	FIPS_TEST_ENC_AUTH_GEN = 1,
> +	FIPS_TEST_DEC_AUTH_VERIF,
> +};
> +
> +#define MAX_LINE_PER_VECTOR            16
> +
> +struct fips_val {
> +	uint8_t *val;
> +	uint32_t len;
> +};
> +
> +struct fips_test_vector {
> +	union {
> +		struct {
> +			struct fips_val key;
> +			struct fips_val digest;
> +			struct fips_val auth_aad;
> +			struct fips_val aad;
> +		} cipher_auth;
> +		struct {
> +			struct fips_val key;
> +			struct fips_val digest;
> +			struct fips_val aad;
> +		} aead;
> +	};
> +
> +	struct fips_val pt;
> +	struct fips_val ct;
> +	struct fips_val iv;
> +
> +	enum rte_crypto_op_status status;
> +};
> +
> +typedef int (*post_prcess_t)(struct fips_val *val);
> +
> +typedef int (*parse_callback_t)(const char *key, char *text,
> +		struct fips_val *val);
> +
> +struct fips_test_callback {
> +	const char *key;
> +	parse_callback_t cb;
> +	struct fips_val *val;
> +};
> +
> +struct fips_test_interim_info {
> +	FILE *fp_rd;
> +	FILE *fp_wr;
> +	enum file_types file_type;
> +	enum fips_test_algorithms algo;
> +	char *one_line_text;
> +	char *vec[MAX_LINE_PER_VECTOR];
> +	uint32_t nb_vec_lines;
> +	//uint8_t cryptodev_id;
remove if not needed
> +	char device_name[MAX_STRING_SIZE];
> +
> +	enum fips_test_op op;
> +
> +	const struct fips_test_callback *callbacks;
> +	const struct fips_test_callback *interim_callbacks;
> +	const struct fips_test_callback *writeback_callbacks;
> +
> +	post_prcess_t parse_writeback;
> +	post_prcess_t kat_check;
> +};
> +
> +extern struct fips_test_vector vec;
> +extern struct fips_test_interim_info info;
> +
> +int
> +fips_test_init(const char *req_file_path, const char *rsp_file_path,
> +		const char *device_name);
> +
> +void
> +fips_test_clear(void);
> +
> +int
> +fips_test_fetch_one_block(void);
> +
> +int
> +fips_test_parse_one_case(void);
> +
> +void
> +fips_test_write_one_case(void);
> +
> +int
> +parser_read_uint8_hex(uint8_t *value, const char *p);
> +
> +int
> +parse_uint8_hex_str(const char *key, char *src, struct fips_val *val);
> +
> +int
> +parse_uint8_known_len_hex_str(const char *key, char *src, struct fips_val *val);
> +
> +int
> +parser_read_uint32_val(const char *key, char *src, struct fips_val *val);
> +
> +int
> +parser_read_uint32_bit_val(const char *key, char *src, struct fips_val *val);
> +
> +int
> +parser_read_uint32(uint32_t *value, char *p);
> +
> +int
> +parser_read_uint32_val(const char *key, char *src, struct fips_val *val);
> +
> +int
> +writeback_hex_str(const char *key, char *dst, struct fips_val *val);
> +
> +void
> +parse_write_hex_str(struct fips_val *src);
> +
> +int
> +update_info_vec(uint32_t count);
> +
> +#endif
> diff --git a/examples/cryptodev_fips_validate/main.c b/examples/cryptodev_fips_validate/main.c
> new file mode 100644
> index 0000000..4f14b04
> --- /dev/null
> +++ b/examples/cryptodev_fips_validate/main.c
> @@ -0,0 +1,388 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2018 Intel Corporation
> + */
> +
> +#include <sys/stat.h>
> +#include <getopt.h>
> +#include <dirent.h>
> +
> +#include <rte_cryptodev.h>
> +#include <rte_cryptodev_pmd.h>
> +#include <rte_mempool.h>
> +#include <rte_mbuf.h>
> +#include <rte_string_fns.h>
> +
> +#include "cryptodev_fips_validate.h"
> +
> +#define REQ_FILE_PATH_KEYWORD	"req-file"
> +#define RSP_FILE_PATH_KEYWORD	"rsp-file"
> +#define FOLDER_KEYWORD		"path-is-folder"
> +#define CRYPTODEV_KEYWORD	"cryptodev"
> +#define CRYPTODEV_ID_KEYWORD	"cryptodev-id"
> +
> +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;
> +	uint32_t dev_id;
> +	struct rte_mempool *mpool;
> +	struct rte_mempool *op_pool;
> +	struct rte_mbuf *mbuf;
> +	struct rte_crypto_op *op;
> +	struct rte_cryptodev_sym_session *sess;
> +} env;
> +
> +static int
> +cryptodev_fips_validate_app_int(void)
> +{
> +	struct rte_cryptodev_config conf = {rte_socket_id(), 1};
> +	struct rte_cryptodev_qp_conf qp_conf = {128};
> +	int ret;
> +
> +	ret = rte_cryptodev_configure(env.dev_id, &conf);
> +	if (ret < 0)
> +		return ret;
> +
> +	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", 128, 0, 0,
> +			UINT16_MAX, rte_socket_id());
> +	if (!env.mpool)
> +		return ret;
> +
> +	ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
> +			rte_socket_id(), env.mpool);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = -ENOMEM;
> +
> +	env.op_pool = rte_crypto_op_pool_create(
> +			"FIPS_OP_POOL",
> +			RTE_CRYPTO_OP_TYPE_SYMMETRIC,
> +			1, 0,
> +			16,
> +			rte_socket_id());
> +	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;
> +
> +	return 0;
> +
> +error_exit:
> +	rte_mempool_free(env.mpool);
> +	if (env.op_pool)
> +		rte_mempool_free(env.op_pool);
> +
> +	return ret;
> +}
> +
> +static void
> +cryptodev_fips_validate_app_uninit(void)
> +{
> +	rte_pktmbuf_free(env.mbuf);
> +	rte_crypto_op_free(env.op);
> +	rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
> +	rte_cryptodev_sym_session_free(env.sess);
> +	rte_mempool_free(env.mpool);
> +	rte_mempool_free(env.op_pool);
> +}
> +
> +static int
> +fips_test_one_file(void);
> +
> +static int
> +parse_cryptodev_arg(char *arg)
> +{
> +	int id = rte_cryptodev_get_dev_id(arg);
> +
> +	if (id < 0) {
> +		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev name %s\n",
> +				id, arg);
> +		return id;
> +	}
> +
> +	env.dev_id = (uint32_t)id;
> +
> +	return 0;
> +}
> +
> +static int
> +parse_cryptodev_id_arg(char *arg)
> +{
> +	uint32_t cryptodev_id;
> +
> +	if (parser_read_uint32(&cryptodev_id, arg) < 0) {
> +		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n",
> +				-EINVAL, arg);
> +		return -1;
> +	}
> +
> +
> +	if (!rte_cryptodev_pmd_is_valid_dev(cryptodev_id)) {
> +		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n",
> +				cryptodev_id, arg);
> +		return -1;
> +	}
> +
> +	env.dev_id = (uint32_t)cryptodev_id;
> +
> +	return 0;
> +}
> +
> +static void
> +cryptodev_fips_validate_usage(const char *prgname)
> +{
> +	printf("%s [EAL options] --\n"
> +		"  --%s: REQUEST-FILE-PATH\n"
> +		"  --%s: RESPONSE-FILE-PATH\n"
> +		"  --%s: indicating both paths are folders\n"
> +		"  --%s: CRYPTODEV-NAME\n"
> +		"  --%s: CRYPTODEV-ID-NAME\n",
> +		prgname, REQ_FILE_PATH_KEYWORD, RSP_FILE_PATH_KEYWORD,
> +		FOLDER_KEYWORD, CRYPTODEV_KEYWORD, CRYPTODEV_ID_KEYWORD);
> +}
> +
> +static int
> +cryptodev_fips_validate_parse_args(int argc, char **argv)
> +{
> +	int opt, ret;
> +	char *prgname = argv[0];
> +	char **argvopt;
> +	int option_index;
> +	struct option lgopts[] = {
> +			{REQ_FILE_PATH_KEYWORD, required_argument, 0, 0},
> +			{RSP_FILE_PATH_KEYWORD, required_argument, 0, 0},
> +			{FOLDER_KEYWORD, no_argument, 0, 0},
> +			{CRYPTODEV_KEYWORD, required_argument, 0, 0},
> +			{CRYPTODEV_ID_KEYWORD, required_argument, 0, 0},
> +			{NULL, 0, 0, 0}
> +	};
> +
> +	argvopt = argv;
> +
> +	while ((opt = getopt_long(argc, argvopt, "s:",
> +				  lgopts, &option_index)) != EOF) {
> +
> +		switch (opt) {
> +		case 0:
> +			if (strcmp(lgopts[option_index].name,
> +					REQ_FILE_PATH_KEYWORD) == 0)
> +				env.req_path = optarg;
> +			else if (strcmp(lgopts[option_index].name,
> +					RSP_FILE_PATH_KEYWORD) == 0)
> +				env.rsp_path = optarg;
> +			else if (strcmp(lgopts[option_index].name,
> +					FOLDER_KEYWORD) == 0)
> +				env.is_path_folder = 1;
> +			else if (strcmp(lgopts[option_index].name,
> +					CRYPTODEV_KEYWORD) == 0) {
> +				ret = parse_cryptodev_arg(optarg);
> +				if (ret < 0) {
> +					cryptodev_fips_validate_usage(prgname);
> +					return -EINVAL;
> +				}
> +			} else if (strcmp(lgopts[option_index].name,
> +					CRYPTODEV_ID_KEYWORD) == 0) {
> +				ret = parse_cryptodev_id_arg(optarg);
> +				if (ret < 0) {
> +					cryptodev_fips_validate_usage(prgname);
> +					return -EINVAL;
> +				}
> +			} else {
> +				cryptodev_fips_validate_usage(prgname);
> +				return -EINVAL;
> +			}
> +			break;
> +		default:
> +			return -1;
> +		}
> +	}
> +
> +	if (env.req_path == NULL || env.rsp_path == NULL ||
> +			env.dev_id == UINT32_MAX) {
> +		cryptodev_fips_validate_usage(prgname);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +int
> +main(int argc, char *argv[])
> +{
> +	int ret;
> +
> +	ret = rte_eal_init(argc, argv);
> +	if (ret < 0) {
> +		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
> +		return -1;
> +	}
> +
> +	argc -= ret;
> +	argv += ret;
> +
> +	ret = cryptodev_fips_validate_parse_args(argc, argv);
> +	if (ret < 0)
> +		rte_exit(EXIT_FAILURE, "Failed to parse arguments!\n");
> +
> +	ret = cryptodev_fips_validate_app_int();
> +	if (ret < 0) {
> +		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
> +		return -1;
> +	}
> +
> +	if (!env.is_path_folder) {
> +		printf("Processing file %s... ", env.req_path);
> +
> +		ret = fips_test_init(env.req_path, env.rsp_path,
> +			rte_cryptodev_name_get(env.dev_id));
> +		if (ret < 0) {
> +			RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
> +					ret, env.req_path);
> +			goto exit;
> +		}
> +
> +
> +		ret = fips_test_one_file();
> +		if (ret < 0) {
> +			RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
> +					ret, env.req_path);
> +			goto exit;
> +		}
> +
> +		printf("Done\n");
> +
> +	} else {
> +		struct dirent *dir;
> +		DIR *d_req, *d_rsp;
> +		char req_path[1024];
> +		char rsp_path[1024];
> +
> +		d_req = opendir(env.req_path);
> +		if (!d_req) {
> +			RTE_LOG(ERR, USER1, "Error %i: Path %s not exist\n",
> +					-EINVAL, env.req_path);
> +			goto exit;
> +		}
> +
> +		d_rsp = opendir(env.rsp_path);
> +		if (!d_rsp) {
> +			ret = mkdir(env.rsp_path, 0700);
> +			if (ret == 0)
> +				d_rsp = opendir(env.rsp_path);
> +			else {
> +				RTE_LOG(ERR, USER1, "Error %i: Invalid %s\n",
> +						-EINVAL, env.rsp_path);
> +				goto exit;
> +			}
> +		}
> +		closedir(d_rsp);
> +
> +		while ((dir = readdir(d_req)) != NULL) {
> +			if (strstr(dir->d_name, "req") == NULL)
> +				continue;
> +
> +			snprintf(req_path, 1023, "%s/%s", env.req_path,
> +					dir->d_name);
> +			snprintf(rsp_path, 1023, "%s/%s", env.rsp_path,
> +					dir->d_name);
> +			strlcpy(strstr(rsp_path, "req"), "rsp", 4);
> +
> +			printf("Processing file %s... ", req_path);
> +
> +			ret = fips_test_init(req_path, rsp_path,
> +			rte_cryptodev_name_get(env.dev_id));
> +			if (ret < 0) {
> +				RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
> +						ret, req_path);
> +				break;
> +			}
> +
> +			ret = fips_test_one_file();
> +			if (ret < 0) {
> +				RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
> +						ret, req_path);
> +				break;
> +			}
> +
> +			printf("Done\n");
> +		}
> +
> +		closedir(d_req);
> +	}
> +
> +
> +exit:
> +	fips_test_clear();
> +	cryptodev_fips_validate_app_uninit();
> +
> +	return ret;
> +
> +}
> +
> +static void
> +print_test_block(void)
> +{
> +	uint32_t i;
> +
> +	for (i = 0; i < info.nb_vec_lines; i++)
> +		printf("%s\n", info.vec[i]);
> +
> +	printf("\n");
> +}
> +
> +static int
> +fips_test_one_file(void)
> +{
> +	int fetch_ret = 0, ret;
> +
> +	while (fetch_ret == 0) {
> +		fetch_ret = fips_test_fetch_one_block();
> +		if (fetch_ret < 0) {
> +			RTE_LOG(ERR, USER1, "Error %i: Fetch block\n",
> +					fetch_ret);
> +			ret = fetch_ret;
> +			goto error_one_case;
> +		}
> +
> +		if (info.nb_vec_lines == 0) {
> +			if (fetch_ret == -EOF)
> +				break;
> +
> +			fprintf(info.fp_wr, "\n");
> +			continue;
> +		}
> +
> +		ret = fips_test_parse_one_case();
> +		switch (ret) {
> +		case 0:
> +			if (ret == 0)
> +				break;
> +			RTE_LOG(ERR, USER1, "Error %i: test block\n",
> +					ret);
this log is unreachable code.
> +			goto error_one_case;
> +		case 1:
> +			break;
> +		default:
> +			RTE_LOG(ERR, USER1, "Error %i: Parse block\n",
> +					ret);
> +			goto error_one_case;
> +		}
do you really need this switch case here. In both the cases you are 
breaking without doing anything.
it should be something like
if (ret <= 0) {
     RTE_LOG(ERR, USER1, "Error %i: Parse block\n", ret);
     goto error_one_case;
}
> +
> +		continue;
> +error_one_case:
> +		print_test_block();
> +	}
> +
> +	fips_test_clear();
> +
> +}
> diff --git a/examples/cryptodev_fips_validate/meson.build b/examples/cryptodev_fips_validate/meson.build
> new file mode 100644
> index 0000000..f44043c
> --- /dev/null
> +++ b/examples/cryptodev_fips_validate/meson.build
> @@ -0,0 +1,14 @@
> +# SPDX-License-Identifier: BSD-3-Clause
> +# Copyright(c) 2018 Intel Corporation
> +
> +# meson file, for building this example as part of a main DPDK build.
> +#
> +# To build this example as a standalone application with an already-installed
> +# DPDK instance, use 'make'
> +
> +deps += ['cryptodev']
> +allow_experimental_apis = true
> +sources = files(
> +	'cryptodev_fips_parse_validate.c',
> +	'main.c'
> +)


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

* Re: [dpdk-dev] [PATCH v5 4/8] examples/cryptodev_fips_validate: add TDES parser and enablement for test types
  2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 4/8] examples/cryptodev_fips_validate: add TDES parser and enablement for test types Marko Kovacevic
@ 2018-10-24 12:31     ` Akhil Goyal
  2018-10-24 14:11       ` Marko Kovacevic
  0 siblings, 1 reply; 52+ messages in thread
From: Akhil Goyal @ 2018-10-24 12:31 UTC (permalink / raw)
  To: Marko Kovacevic, dev; +Cc: roy.fan.zhang, arkadiuszx.kusztal

better to be uniform with the name
TDES or 3DES


On 10/17/2018 6:19 PM, Marko Kovacevic wrote:
> Added enablement for TDES parser, to allow the
> application to parser the TDES request files and to validate all
> test types supported.
>
> Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
> Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
> Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
> ---
>   examples/cryptodev_fips_validate/Makefile          |   1 +
>   .../cryptodev_fips_parse_3des.c                    | 259 +++++++++++++++++++++
>   .../cryptodev_fips_parse_aes.c                     |   2 +
>   .../cryptodev_fips_parse_validate.c                |   5 +
>   .../cryptodev_fips_validate.h                      |  21 ++
>   examples/cryptodev_fips_validate/main.c            | 175 ++++++++++++++
>   examples/cryptodev_fips_validate/meson.build       |   1 +
>   7 files changed, 464 insertions(+)
>   create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c
>
> diff --git a/examples/cryptodev_fips_validate/Makefile b/examples/cryptodev_fips_validate/Makefile
> index c85c76c..2ddf326 100644
> --- a/examples/cryptodev_fips_validate/Makefile
> +++ b/examples/cryptodev_fips_validate/Makefile
> @@ -7,6 +7,7 @@ APP = fips_validation
>   # all source are stored in SRCS-y
>   SRCS-y := cryptodev_fips_parse_aes.c
>   SRCS-y += cryptodev_fips_parse_hmac.c
> +SRCS-y += cryptodev_fips_parse_3des.c
>   SRCS-y += cryptodev_fips_parse_validate.c
>   SRCS-y += main.c
>   
> diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c
> new file mode 100644
> index 0000000..82e9132
> --- /dev/null
> +++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c
> @@ -0,0 +1,259 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2018 Intel Corporation
> + */
> +
> +#include <string.h>
> +#include <stdio.h>
> +
> +#include <rte_malloc.h>
> +#include <rte_cryptodev.h>
> +
> +#include "cryptodev_fips_validate.h"
> +
> +#define NEW_LINE_STR	"#"
> +#define TEST_TYPE_KEY	" for CBC"
> +#define TEST_CBCI_KEY	" for CBCI"
> +
> +#define ENC_STR		"[ENCRYPT]"
> +#define DEC_STR		"[DECRYPT]"
> +
> +#define COUNT_STR	"COUNT = "
> +#define KEY1_STR	"KEY1 = "
> +#define KEY2_STR	"KEY2 = "
> +#define KEY3_STR	"KEY3 = "
> +
> +#define KEYS_STR	"KEYs = "
> +#define IV_STR		"IV = "
> +#define PT_STR		"PLAINTEXT = "
> +#define CT_STR		"CIPHERTEXT = "
> +#define NK_STR		"NumKeys = "
> +
> +#define SET_STR		" = "
> +
> +#define PLAIN_TEXT	0
> +#define CIPHER_TEXT	1
> +#define KEY_TEXT	2
> +#define IV_TEXT		3
> +
> +#define DEVICE_STR	"# Config Info for : "
> +
> +struct {
> +	uint32_t type;
> +	const char *desc;
> +} test_types[] = {
> +		{TDES_INVERSE_PERMUTATION, "INVERSE PERMUTATION"},
> +		{TDES_PERMUTATION, "PERMUTATION OPERATION"},
> +		{TDES_SUBSTITUTION_TABLE, "SUBSTITUTION TABLE"},
> +		{TDES_VARIABLE_KEY, "VARIABLE KEY"},
> +		{TDES_VARIABLE_TEXT, "VARIABLE PLAINTEXT/CIPHERTEXT"},
> +		{TDES_VARIABLE_TEXT, "KAT"},
> +		{TDES_MCT, "Monte Carlo (Modes) Test"},
> +		{TDES_MMT, "Multi block Message Test"},
> +};
> +
> +static int
> +writeback_tdes_hex_str(const char *key, char *dst, struct fips_val *val);
> +
> +static int
> +parse_3des_uint8_hex_str(const char *key, char *src, struct fips_val *val);
> +
> +static int
> +parse_tdes_interim(const char *key,
> +		__attribute__((__unused__)) char *text,
> +		struct fips_val *val);
> +
> +struct fips_test_callback tdes_tests_vectors[] = {
> +		{KEYS_STR, parse_3des_uint8_hex_str, &vec.cipher_auth.key},
> +		{KEY1_STR, parse_3des_uint8_hex_str, &vec.cipher_auth.key},
> +		{KEY2_STR, parse_3des_uint8_hex_str, &vec.cipher_auth.key},
> +		{KEY3_STR, parse_3des_uint8_hex_str, &vec.cipher_auth.key},
> +		{IV_STR, parse_uint8_hex_str, &vec.iv},
> +		{PT_STR, parse_uint8_hex_str, &vec.pt},
> +		{CT_STR, parse_uint8_hex_str, &vec.ct},
> +		{NULL, NULL, NULL} /**< end pointer */
> +};
> +
> +struct fips_test_callback tdes_tests_interim_vectors[] = {
> +		{ENC_STR, parse_tdes_interim, NULL},
> +		{DEC_STR, parse_tdes_interim, NULL},
> +		{NULL, NULL, NULL} /**< end pointer */
> +};
> +
> +struct fips_test_callback tdes_writeback_callbacks[] = {
> +		/** First element is used to pass COUNT string */
> +		{COUNT_STR, NULL, NULL},
> +		{IV_STR, writeback_hex_str, &vec.iv},
> +		{KEY1_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
> +		{KEY2_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
> +		{KEY3_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
> +		{KEYS_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
> +		{PT_STR, writeback_hex_str, &vec.pt},
> +		{CT_STR, writeback_hex_str, &vec.ct},
> +		{NULL, NULL, NULL} /**< end pointer */
> +};
> +
> +static int
> +parse_tdes_interim(const char *key,
> +		__attribute__((__unused__)) char *text,
> +		__attribute__((__unused__)) struct fips_val *val)
> +{
> +	if (strstr(key, ENC_STR))
> +		info.op = FIPS_TEST_ENC_AUTH_GEN;
> +	else if (strstr(key, DEC_STR))
> +		info.op = FIPS_TEST_DEC_AUTH_VERIF;
> +	else if (strstr(NK_STR, "NumKeys = 1"))
> +		info.interim_info.tdes_data.nb_keys = 1;
> +	else if (strstr(NK_STR, "NumKeys = 2"))
> +		info.interim_info.tdes_data.nb_keys = 2;
> +	else if (strstr(NK_STR, "NumKeys = 3"))
> +		info.interim_info.tdes_data.nb_keys = 3;
> +	else
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int
> +parse_3des_uint8_hex_str(const char *key, char *src, struct fips_val *val)
> +{
> +	uint8_t tmp_key[24] = {0};
> +	uint32_t len, i;
> +
> +	src += strlen(key);
> +
> +	len = strlen(src) / 2;
> +
> +	if (val->val) {
> +		memcpy(tmp_key, val->val, val->len);
> +		rte_free(val->val);
> +	}
> +
> +	val->val = rte_zmalloc(NULL, 24, 0);
> +	if (!val->val)
> +		return -1;
> +
> +	memcpy(val->val, tmp_key, 24);
> +
> +	if (strstr(key, KEYS_STR)) {
> +		for (i = 0; i < len; i++) {
> +			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
> +
> +			if (parser_read_uint8_hex(&val->val[i], byte) < 0)
> +				return -EINVAL;
memory leak for val->val
> +		}
> +
> +		memcpy(val->val + 8, val->val, 8);
> +		memcpy(val->val + 16, val->val, 8);
> +
> +	} else if (strstr(key, KEY1_STR)) {
> +		for (i = 0; i < len; i++) {
> +			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
> +
> +			if (parser_read_uint8_hex(&val->val[i], byte) < 0)
> +				return -EINVAL;
> +		}
> +
> +		if (info.interim_info.tdes_data.nb_keys == 2)
> +			memcpy(val->val + 16, val->val, 8);
> +
> +	} else if (strstr(key, KEY2_STR)) {
> +		for (i = 0; i < len; i++) {
> +			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
> +
> +			if (parser_read_uint8_hex(&val->val[i + 8], byte) < 0)
> +				return -EINVAL;
> +		}
> +
> +	} else if (strstr(key, KEY3_STR)) {
> +		for (i = 0; i < len; i++) {
> +			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
> +
> +			if (parser_read_uint8_hex(&val->val[i + 16], byte) < 0)
> +				return -EINVAL;
> +		}
> +	} else
> +		return -EINVAL;
> +
> +	val->len = 24;
> +
> +	return 0;
> +}
> +
>


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

* Re: [dpdk-dev] [PATCH v5 2/8] examples/cryptodev_fips_validate: add aes parser and enablement for test types
  2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 2/8] examples/cryptodev_fips_validate: add aes parser and enablement for test types Marko Kovacevic
@ 2018-10-24 12:37     ` Akhil Goyal
  2018-10-24 14:18       ` Marko Kovacevic
  0 siblings, 1 reply; 52+ messages in thread
From: Akhil Goyal @ 2018-10-24 12:37 UTC (permalink / raw)
  To: Marko Kovacevic, dev; +Cc: roy.fan.zhang, arkadiuszx.kusztal



On 10/17/2018 6:19 PM, Marko Kovacevic wrote:
> diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
> index beb6bed..5ac858d 100644
> --- a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
> +++ b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
> @@ -23,6 +23,7 @@
>   #define FAX_FILE_PERFIX		"fax"
>   
>   enum fips_test_algorithms {
> +		FIPS_TEST_ALGO_AES = 0,
>   		FIPS_TEST_ALGO_MAX
>   };
>   
> @@ -77,6 +78,21 @@ struct fips_test_callback {
>   	struct fips_val *val;
>   };
>   
> +enum fips_aesavs_test_types {
> +	AESAVS_TYPE_GFXBOX = 0,
> +	AESAVS_TYPE_KEYSBOX,
> +	AESAVS_TYPE_VARKEY,
> +	AESAVS_TYPE_VARTXT,
> +	AESAVS_TYPE_MMT,
> +	AESAVS_TYPE_MCT,
> +};
It would be better to start the enums from 1. Consider a case when an 
uninitialized/unsupported type is accidentally used and it would be 
treated as AES and would be processed accordingly.

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

* Re: [dpdk-dev] [PATCH v5 8/8] doc/guides/sample_app_ug: add guides for fips validation
  2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 8/8] doc/guides/sample_app_ug: add guides for fips validation Marko Kovacevic
@ 2018-10-24 12:51     ` Akhil Goyal
  0 siblings, 0 replies; 52+ messages in thread
From: Akhil Goyal @ 2018-10-24 12:51 UTC (permalink / raw)
  To: Marko Kovacevic, dev, john.mcnamara; +Cc: roy.fan.zhang, arkadiuszx.kusztal

++ John

On 10/17/2018 6:19 PM, Marko Kovacevic wrote:
> Document explains how to run the fips sample app
> and instructions users need to parser all the request
> files and generate the response files.
>
> Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
> Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
> Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
> ---
>   MAINTAINERS                                  |   4 +
>   doc/guides/rel_notes/release_18_11.rst       |   6 ++
>   doc/guides/sample_app_ug/fips_validation.rst | 119 +++++++++++++++++++++++++++
>   doc/guides/sample_app_ug/index.rst           |   1 +
>   4 files changed, 130 insertions(+)
>   create mode 100644 doc/guides/sample_app_ug/fips_validation.rst
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 5d73756..31c9c65 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1314,3 +1314,7 @@ F: examples/tep_termination/
>   F: examples/vmdq/
>   F: examples/vmdq_dcb/
>   F: doc/guides/sample_app_ug/vmdq_dcb_forwarding.rst
> +
> +M: Marko Kovacevic <marko.kovacevic@intel.com>
> +F: examples/cryptodev_fips_validate
> +F: doc/guides/sample_app_ug/fips_validation.rst
> diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
> index 436b20e..83ad92e 100644
> --- a/doc/guides/rel_notes/release_18_11.rst
> +++ b/doc/guides/rel_notes/release_18_11.rst
> @@ -54,6 +54,12 @@ New Features
>        Also, make sure to start the actual text at the margin.
>        =========================================================
>   
> +* **Added Cryptodev Fips Validation Example Application.**
> +
> +  Added an example application to parse and perform symmetric cryptography
> +  computation to the NIST Cryptographic Algorithm Validation Program (CAVP)
> +  test vectors.
> +
>   * **Added support for using externally allocated memory in DPDK.**
>   
>     DPDK has gained support for creating new ``rte_malloc`` heaps referencing
> diff --git a/doc/guides/sample_app_ug/fips_validation.rst b/doc/guides/sample_app_ug/fips_validation.rst
> new file mode 100644
> index 0000000..9e0db23
> --- /dev/null
> +++ b/doc/guides/sample_app_ug/fips_validation.rst
> @@ -0,0 +1,119 @@
> +..  SPDX-License-Identifier: BSD-3-Clause
> +    Copyright(c) 2018 Intel Corporation.
> +
> +Federal Information Processing Standards (FIPS) CryptoDev Validation
> +====================================================================
> +
> +Overview
> +--------
> +
> +Federal Information Processing Standards (FIPS) are publicly announced standards
> +developed by the United States federal government for use in computer systems by
> +non-military government agencies and government contractors.
> +
> +This application is used to parse and perform symmetric cryptography
> +computation to the NIST Cryptographic Algorithm Validation Program (CAVP) test
> +vectors.
> +
> +For an algorithm implementation to be listed on a cryptographic module
> +validation certificate as an Approved security function, the algorithm
> +implementation must meet all the requirements of FIPS 140-2 and must
> +successfully complete the cryptographic algorithm validation process.
> +
> +Limitations
> +-----------
> +
> +* Only NIST CAVP request files are parsed by this application.
> +* The version of request file supported is ``CAVS 21.0``
> +* If the header comment in a ``.req`` file does not contain a Algo tag
> +  i.e ``AES,TDES,GCM`` you need to manually add it into the head comment for
> +  example::
> +
> +      # VARIABLE KEY - KAT for CBC / # TDES VARIABLE KEY - KAT for CBC
> +
> +* The application does not supply the test vectors. The user is expected to
> +  obtain the test vector files from `NIST
> +  <https://csrc.nist.gov/projects/cryptographic-algorithm-validation-
> +  program/block-ciphers>`_ website. To obtain the ``.req`` files you need to
> +  email a person from the NIST webiste and pay for the ``.req`` files.
> +  The ``.rsp`` files from the site can be used to validate and compare with
> +  the ``.rsp`` files created by the FIPS application.
> +
> +* Supported test vectors
> +    * AES-CBC (128,192,256) - GFSbox, KeySbox, MCT, MMT
> +    * AES-GCM (128,192,256) - EncryptExtIV, Decrypt
> +    * AES-CCM (128) - VADT, VNT, VPT, VTT, DVPT
> +    * AES-CMAC (128) - Generate, Verify
> +    * HMAC (SHA1, SHA224, SHA256, SHA384, SHA512)
> +    * TDES-CBC (1 Key, 2 Keys, 3 Keys) - MMT, Monte, Permop, Subkey, Varkey,
> +      VarText
> +
> +Compiling the Application
> +-------------------------
> +
> +* Compile Application
> +
> +    .. code-block:: console
> +
> +         make -C examples/cryptodev_fips_validate
> +
> +*  Run ``dos2unix`` on the request files
> +
> +    .. code-block:: console
> +
> +         dos2unix AES/req/*
> +         dos2unix AES_GCM/req/*
> +         dos2unix CCM/req/*
> +         dos2unix CMAC/req/*
> +         dos2unix HMAC/req/*
> +         dos2unix TDES/req/*
> +
> +Running the Application
> +-----------------------
> +
> +The application requires a number of command line options:
> +
> +    .. code-block:: console
> +
> +         ./cryptodev_fips_validate_app [EAL options]
> +         -- --req-file FILE_PATH/FOLDER_PATH
> +         --rsp-file FILE_PATH/FOLDER_PATH
> +         [--cryptodev DEVICE_NAME] [--cryptodev-id ID] [--path-is-folder]
> +
> +where,
> +  * req-file: The path of the request file or folder, separated by
> +    ``path-is-folder`` option.
> +
> +  * rsp-file: The path that the response file or folder is stored. separated by
> +    ``path-is-folder`` option.
> +
> +  * cryptodev: The name of the target DPDK Crypto device to be validated.
> +
> +  * cryptodev-id: The id of the target DPDK Crypto device to be validated.
> +
> +  * path-is-folder: If presented the application expects req-file and rsp-file
> +    are folder paths.
> +
> +.. note::
> +
> +    The .req file is optional and the application can be run without it, but
> +    .req files are the only ones that will be parsed by the application.
I am a bit confused here, I believe .rsp files downloaded from the 
website can be used to run the application
as it has both the cipher as well as plain text. So the application will 
be able to compare the data from .rsp file only.
Could you please elaborate both the scenarios of running the application 
with and without .req file.
> +
> +To run the application in linuxapp environment to test one AES FIPS test data
> +file for crypto_aesni_mb PMD, issue the command:
> +
> +.. code-block:: console
> +
> +    $ ./cryptodev_fips_validate_app --vdev crypto_aesni_mb --
> +    --req-file /PATH/TO/REQUEST/FILE.req --rsp-file ./PATH/TO/RESPONSE/FILE.rsp
> +    --cryptodev crypto_aesni_mb
> +
> +To run the application in linuxapp environment to test all AES-GCM FIPS test
> +data files in one folder for crypto_aesni_gcm PMD, issue the command:
> +
> +.. code-block:: console
> +
> +    $ ./cryptodev_fips_validate_app --vdev crypto_aesni_gcm0 --
> +    --req-file /PATH/TO/REQUEST/FILE/FOLDER/
> +    --rsp-file ./PATH/TO/RESPONSE/FILE/FOLDER/
> +    --cryptodev-id 0 --path-is-folder
> diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst
> index 74b12af..65c12d9 100644
> --- a/doc/guides/sample_app_ug/index.rst
> +++ b/doc/guides/sample_app_ug/index.rst
> @@ -57,6 +57,7 @@ Sample Applications User Guides
>       performance_thread
>       ipsec_secgw
>       bbdev_app
> +    fips_validation
>   
>   **Figures**
>   


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

* Re: [dpdk-dev] [PATCH v5 4/8] examples/cryptodev_fips_validate: add TDES parser and enablement for test types
  2018-10-24 12:31     ` Akhil Goyal
@ 2018-10-24 14:11       ` Marko Kovacevic
  0 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-24 14:11 UTC (permalink / raw)
  To: Akhil Goyal, dev; +Cc: roy.fan.zhang, arkadiuszx.kusztal


On 24/10/2018 13:31, Akhil Goyal wrote:
> better to be uniform with the name
> TDES or 3DES
sure will make it uniform
>
> On 10/17/2018 6:19 PM, Marko Kovacevic wrote:
>> Added enablement for TDES parser, to allow the
>> application to parser the TDES request files and to validate all
>> test types supported.
>>
>> Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
>> Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
>> Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
>> ---
>>    examples/cryptodev_fips_validate/Makefile          |   1 +
>>    .../cryptodev_fips_parse_3des.c                    | 259 +++++++++++++++++++++
>>    .../cryptodev_fips_parse_aes.c                     |   2 +
>>    .../cryptodev_fips_parse_validate.c                |   5 +
>>    .../cryptodev_fips_validate.h                      |  21 ++
>>    examples/cryptodev_fips_validate/main.c            | 175 ++++++++++++++
>>    examples/cryptodev_fips_validate/meson.build       |   1 +
>>    7 files changed, 464 insertions(+)
>>    create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c
>>
>> diff --git a/examples/cryptodev_fips_validate/Makefile b/examples/cryptodev_fips_validate/Makefile
>> index c85c76c..2ddf326 100644
>> --- a/examples/cryptodev_fips_validate/Makefile
>> +++ b/examples/cryptodev_fips_validate/Makefile
>> @@ -7,6 +7,7 @@ APP = fips_validation
>>    # all source are stored in SRCS-y
>>    SRCS-y := cryptodev_fips_parse_aes.c
>>    SRCS-y += cryptodev_fips_parse_hmac.c
>> +SRCS-y += cryptodev_fips_parse_3des.c
>>    SRCS-y += cryptodev_fips_parse_validate.c
>>    SRCS-y += main.c
>>    
>> diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c
>> new file mode 100644
>> index 0000000..82e9132
>> --- /dev/null
>> +++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c
>> @@ -0,0 +1,259 @@
>> +/* SPDX-License-Identifier: BSD-3-Clause
>> + * Copyright(c) 2018 Intel Corporation
>> + */
>> +
>> +#include <string.h>
>> +#include <stdio.h>
>> +
>> +#include <rte_malloc.h>
>> +#include <rte_cryptodev.h>
>> +
>> +#include "cryptodev_fips_validate.h"
>> +
>> +#define NEW_LINE_STR	"#"
>> +#define TEST_TYPE_KEY	" for CBC"
>> +#define TEST_CBCI_KEY	" for CBCI"
>> +
>> +#define ENC_STR		"[ENCRYPT]"
>> +#define DEC_STR		"[DECRYPT]"
>> +
>> +#define COUNT_STR	"COUNT = "
>> +#define KEY1_STR	"KEY1 = "
>> +#define KEY2_STR	"KEY2 = "
>> +#define KEY3_STR	"KEY3 = "
>> +
>> +#define KEYS_STR	"KEYs = "
>> +#define IV_STR		"IV = "
>> +#define PT_STR		"PLAINTEXT = "
>> +#define CT_STR		"CIPHERTEXT = "
>> +#define NK_STR		"NumKeys = "
>> +
>> +#define SET_STR		" = "
>> +
>> +#define PLAIN_TEXT	0
>> +#define CIPHER_TEXT	1
>> +#define KEY_TEXT	2
>> +#define IV_TEXT		3
>> +
>> +#define DEVICE_STR	"# Config Info for : "
>> +
>> +struct {
>> +	uint32_t type;
>> +	const char *desc;
>> +} test_types[] = {
>> +		{TDES_INVERSE_PERMUTATION, "INVERSE PERMUTATION"},
>> +		{TDES_PERMUTATION, "PERMUTATION OPERATION"},
>> +		{TDES_SUBSTITUTION_TABLE, "SUBSTITUTION TABLE"},
>> +		{TDES_VARIABLE_KEY, "VARIABLE KEY"},
>> +		{TDES_VARIABLE_TEXT, "VARIABLE PLAINTEXT/CIPHERTEXT"},
>> +		{TDES_VARIABLE_TEXT, "KAT"},
>> +		{TDES_MCT, "Monte Carlo (Modes) Test"},
>> +		{TDES_MMT, "Multi block Message Test"},
>> +};
>> +
>> +static int
>> +writeback_tdes_hex_str(const char *key, char *dst, struct fips_val *val);
>> +
>> +static int
>> +parse_3des_uint8_hex_str(const char *key, char *src, struct fips_val *val);
>> +
>> +static int
>> +parse_tdes_interim(const char *key,
>> +		__attribute__((__unused__)) char *text,
>> +		struct fips_val *val);
>> +
>> +struct fips_test_callback tdes_tests_vectors[] = {
>> +		{KEYS_STR, parse_3des_uint8_hex_str, &vec.cipher_auth.key},
>> +		{KEY1_STR, parse_3des_uint8_hex_str, &vec.cipher_auth.key},
>> +		{KEY2_STR, parse_3des_uint8_hex_str, &vec.cipher_auth.key},
>> +		{KEY3_STR, parse_3des_uint8_hex_str, &vec.cipher_auth.key},
>> +		{IV_STR, parse_uint8_hex_str, &vec.iv},
>> +		{PT_STR, parse_uint8_hex_str, &vec.pt},
>> +		{CT_STR, parse_uint8_hex_str, &vec.ct},
>> +		{NULL, NULL, NULL} /**< end pointer */
>> +};
>> +
>> +struct fips_test_callback tdes_tests_interim_vectors[] = {
>> +		{ENC_STR, parse_tdes_interim, NULL},
>> +		{DEC_STR, parse_tdes_interim, NULL},
>> +		{NULL, NULL, NULL} /**< end pointer */
>> +};
>> +
>> +struct fips_test_callback tdes_writeback_callbacks[] = {
>> +		/** First element is used to pass COUNT string */
>> +		{COUNT_STR, NULL, NULL},
>> +		{IV_STR, writeback_hex_str, &vec.iv},
>> +		{KEY1_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
>> +		{KEY2_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
>> +		{KEY3_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
>> +		{KEYS_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
>> +		{PT_STR, writeback_hex_str, &vec.pt},
>> +		{CT_STR, writeback_hex_str, &vec.ct},
>> +		{NULL, NULL, NULL} /**< end pointer */
>> +};
>> +
>> +static int
>> +parse_tdes_interim(const char *key,
>> +		__attribute__((__unused__)) char *text,
>> +		__attribute__((__unused__)) struct fips_val *val)
>> +{
>> +	if (strstr(key, ENC_STR))
>> +		info.op = FIPS_TEST_ENC_AUTH_GEN;
>> +	else if (strstr(key, DEC_STR))
>> +		info.op = FIPS_TEST_DEC_AUTH_VERIF;
>> +	else if (strstr(NK_STR, "NumKeys = 1"))
>> +		info.interim_info.tdes_data.nb_keys = 1;
>> +	else if (strstr(NK_STR, "NumKeys = 2"))
>> +		info.interim_info.tdes_data.nb_keys = 2;
>> +	else if (strstr(NK_STR, "NumKeys = 3"))
>> +		info.interim_info.tdes_data.nb_keys = 3;
>> +	else
>> +		return -EINVAL;
>> +
>> +	return 0;
>> +}
>> +
>> +static int
>> +parse_3des_uint8_hex_str(const char *key, char *src, struct fips_val *val)
>> +{
>> +	uint8_t tmp_key[24] = {0};
>> +	uint32_t len, i;
>> +
>> +	src += strlen(key);
>> +
>> +	len = strlen(src) / 2;
>> +
>> +	if (val->val) {
>> +		memcpy(tmp_key, val->val, val->len);
>> +		rte_free(val->val);
>> +	}
>> +
>> +	val->val = rte_zmalloc(NULL, 24, 0);
>> +	if (!val->val)
>> +		return -1;
>> +
>> +	memcpy(val->val, tmp_key, 24);
>> +
>> +	if (strstr(key, KEYS_STR)) {
>> +		for (i = 0; i < len; i++) {
>> +			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
>> +
>> +			if (parser_read_uint8_hex(&val->val[i], byte) < 0)
>> +				return -EINVAL;
> memory leak for val->val
good catch will fix it.
>> +		}
>> +
>> +		memcpy(val->val + 8, val->val, 8);
>> +		memcpy(val->val + 16, val->val, 8);
>> +
>> +	} else if (strstr(key, KEY1_STR)) {
>> +		for (i = 0; i < len; i++) {
>> +			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
>> +
>> +			if (parser_read_uint8_hex(&val->val[i], byte) < 0)
>> +				return -EINVAL;
>> +		}
>> +
>> +		if (info.interim_info.tdes_data.nb_keys == 2)
>> +			memcpy(val->val + 16, val->val, 8);
>> +
>> +	} else if (strstr(key, KEY2_STR)) {
>> +		for (i = 0; i < len; i++) {
>> +			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
>> +
>> +			if (parser_read_uint8_hex(&val->val[i + 8], byte) < 0)
>> +				return -EINVAL;
>> +		}
>> +
>> +	} else if (strstr(key, KEY3_STR)) {
>> +		for (i = 0; i < len; i++) {
>> +			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
>> +
>> +			if (parser_read_uint8_hex(&val->val[i + 16], byte) < 0)
>> +				return -EINVAL;
>> +		}
>> +	} else
>> +		return -EINVAL;
>> +
>> +	val->len = 24;
>> +
>> +	return 0;
>> +}
>> +
>>

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

* Re: [dpdk-dev] [PATCH v5 1/8] examples/cryptodev_fips_validate: add fips validation into examples
  2018-10-24 12:13     ` Akhil Goyal
@ 2018-10-24 14:17       ` Marko Kovacevic
  2018-10-24 14:36         ` Akhil Goyal
  0 siblings, 1 reply; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-24 14:17 UTC (permalink / raw)
  To: Akhil Goyal, dev; +Cc: roy.fan.zhang, arkadiuszx.kusztal


On 24/10/2018 13:13, Akhil Goyal wrote:
>
> On 10/17/2018 6:19 PM, Marko Kovacevic wrote:
>> Added FIPS application into the examples to allow
>> users to use a simple sample app to validate
>> their systems and be able to get FIPS certification.
>>
>> Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
>> Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
>> Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
>> ---
>>    examples/cryptodev_fips_validate/Makefile          |  69 +++
>>    .../cryptodev_fips_parse_validate.c                | 562 +++++++++++++++++++++
>>    .../cryptodev_fips_validate.h                      | 150 ++++++
>>    examples/cryptodev_fips_validate/main.c            | 388 ++++++++++++++
>>    examples/cryptodev_fips_validate/meson.build       |  14 +
>>    5 files changed, 1183 insertions(+)
>>    create mode 100644 examples/cryptodev_fips_validate/Makefile
>>    create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
>>    create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_validate.h
>>    create mode 100644 examples/cryptodev_fips_validate/main.c
>>    create mode 100644 examples/cryptodev_fips_validate/meson.build
>>
>> diff --git a/examples/cryptodev_fips_validate/Makefile b/examples/cryptodev_fips_validate/Makefile
>> new file mode 100644
>> index 0000000..7f0e603
>> --- /dev/null
>> +++ b/examples/cryptodev_fips_validate/Makefile
>> @@ -0,0 +1,69 @@
>> +# SPDX-License-Identifier: BSD-3-Clause
>> +# Copyright(c) 2010-2014 Intel Corporation
> I believe this is a copy paste error, it should be 2018
Yeah your right will make the change.
>> +
>> +# binary name
>> +APP = fips_validation
>> +
>> +# all source are stored in SRCS-y
>> +SRCS-y += cryptodev_fips_parse_validate.c
>> +SRCS-y += main.c
>> +
>> +# Build using pkg-config variables if possible
>> +$(shell pkg-config --exists libdpdk)
>> +ifeq ($(.SHELLSTATUS),0)
>> +
>> +all: shared
>> +.PHONY: shared static
>> +shared: build/$(APP)-shared
>> +	ln -sf $(APP)-shared build/$(APP)
>> +static: build/$(APP)-static
>> +	ln -sf $(APP)-static build/$(APP)
>> +
>> +PC_FILE := $(shell pkg-config --path libdpdk)
>> +CFLAGS += -O3 $(shell pkg-config --cflags libdpdk)
>> +LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk)
>> +LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk)
>> +
>> +build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
>> +	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
>> +
>> +build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build
>> +	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC)
>> +
>> +build:
>> +	@mkdir -p $@
>> +
>> +.PHONY: clean
>> +clean:
>> +	rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared
>> +	rmdir --ignore-fail-on-non-empty build
>> +
>> +else
>> +
>> +ifeq ($(RTE_SDK),)
>> +$(error "Please define RTE_SDK environment variable")
>> +endif
>> +
>> +# Default target, can be overridden by command line or environment
>> +RTE_TARGET ?= x86_64-native-linuxapp-gcc
>> +
>> +INC += $(sort $(wildcard *.h))
>> +
>> +include $(RTE_SDK)/mk/rte.vars.mk
>> +
>> +CFLAGS += $(WERROR_FLAGS)
>> +
>> +# workaround for a gcc bug with noreturn attribute
>> +# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603
>> +ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
>> +CFLAGS_main.o += -Wno-return-type
>> +endif
>> +
>> +CFLAGS += -DALLOW_EXPERIMENTAL_API
>> +CFLAGS += -I$(SRCDIR)
>> +CFLAGS += -O3
>> +CFLAGS += $(WERROR_FLAGS)
>> +
>> +include $(RTE_SDK)/mk/rte.extapp.mk
>> +
>> +endif
>> diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
>> new file mode 100644
>> index 0000000..aec5bb9
>> --- /dev/null
>> +++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
>> @@ -0,0 +1,562 @@
>> +/* SPDX-License-Identifier: BSD-3-Clause
>> + * Copyright(c) 2018 Intel Corporation
>> + */
>> +
>> +#include <stdio.h>
>> +#include <string.h>
>> +
>> +#include <rte_string_fns.h>
>> +#include <rte_cryptodev.h>
>> +#include <rte_malloc.h>
>> +
>> +#include "cryptodev_fips_validate.h"
>> +
>> +#define skip_white_spaces(pos)			\
>> +({						\
>> +	__typeof__(pos) _p = (pos);		\
>> +	for ( ; isspace(*_p); _p++)		\
>> +		;				\
>> +	_p;					\
>> +})
>> +
>> +static int
>> +get_file_line(void)
>> +{
>> +	FILE *fp = info.fp_rd;
>> +	char *line = info.one_line_text;
>> +	char c;
>> +	uint32_t loc = 0;
>> +
>> +	memset(line, 0, MAX_LINE_CHAR);
>> +	while ((c = fgetc(fp)) != EOF) {
>> +		if (loc >= MAX_LINE_CHAR - 1)
>> +			return -ENOMEM;
>> +		if (c == '\n')
>> +			return 0;
>> +		line[loc++] = c;
>> +	}
>> +
>> +	if (c == EOF)
>> +		return -EOF;
>> +
>> +	return 0;
>> +}
>> +
>> +int
>> +fips_test_fetch_one_block(void)
>> +{
>> +	size_t size;
>> +	int ret = 0;
>> +	uint32_t i;
>> +
>> +	for (i = 0; i < info.nb_vec_lines; i++) {
>> +		free(info.vec[i]);
>> +		info.vec[i] = NULL;
>> +	}
>> +
>> +	i = 0;
>> +	do {
>> +		if (i >= MAX_LINE_PER_VECTOR) {
>> +			ret = -ENOMEM;
>> +			goto error_exit;
>> +		}
>> +
>> +		ret = get_file_line();
>> +		size = strlen(info.one_line_text);
>> +		if (size == 0)
>> +			break;
>> +
>> +		info.vec[i] = calloc(1, size + 5);
>> +		if (info.vec[i] == NULL)
>> +			goto error_exit;
>> +
>> +		strlcpy(info.vec[i], info.one_line_text, size + 1);
>> +		i++;
>> +	} while (ret == 0);
>> +
>> +	info.nb_vec_lines = i;
>> +
>> +	return ret;
>> +
>> +error_exit:
>> +	for (i = 0; i < MAX_LINE_PER_VECTOR; i++)
>> +		if (info.vec[i] != NULL) {
>> +			free(info.vec[i]);
>> +			info.vec[i] = NULL;
>> +		}
>> +
>> +	info.nb_vec_lines = 0;
>> +
>> +	return -ENOMEM;
>> +}
>> +
>> +static int
>> +fips_test_parse_header(void)
>> +{
>> +	uint32_t i;
>> +	char *tmp;
>> +	int ret;
>> +	time_t t = time(NULL);
>> +	struct tm *tm_now = localtime(&t);
>> +
>> +	ret = fips_test_fetch_one_block();
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	for (i = 0; i < info.nb_vec_lines; i++) {
>> +
>> +		tmp = strstr(info.vec[i], "# Config info for ");
>> +		if (tmp != NULL) {
>> +			fprintf(info.fp_wr, "%s%s\n", "# Config info for DPDK Cryptodev ",
>> +					info.device_name);
>> +			continue;
>> +		}
>> +
>> +		tmp = strstr(info.vec[i], "#  HMAC information for ");
>> +		if (tmp != NULL) {
>> +			fprintf(info.fp_wr, "%s%s\n", "#  HMAC information for "
>> +				"DPDK Cryptodev ",
>> +				info.device_name);
>> +			continue;
>> +		}
>> +
>> +		tmp = strstr(info.vec[i], "# Config Info for : ");
>> +		if (tmp != NULL) {
>> +
>> +			fprintf(info.fp_wr, "%s%s\n", "# Config Info for DPDK Cryptodev : ",
>> +					info.device_name);
>> +			continue;
>> +		}
>> +
>> +		tmp = strstr(info.vec[i], "# information for ");
>> +		if (tmp != NULL) {
>> +
>> +			char tmp_output[128] = {0};
>> +
>> +			strlcpy(tmp_output, info.vec[i], tmp - info.vec[i] + 1);
>> +
>> +			fprintf(info.fp_wr, "%s%s%s\n", tmp_output,
>> +					"information for DPDK Cryptodev ",
>> +					info.device_name);
>> +			continue;
>> +		}
>> +
>> +		tmp = strstr(info.vec[i], " test information for ");
>> +		if (tmp != NULL) {
>> +			char tmp_output[128] = {0};
>> +
>> +			strlcpy(tmp_output, info.vec[i], tmp - info.vec[i] + 1);
>> +
>> +			fprintf(info.fp_wr, "%s%s%s\n", tmp_output,
>> +					"test information for DPDK Cryptodev ",
>> +					info.device_name);
>> +			continue;
>> +		}
>> +
>> +		if (i == info.nb_vec_lines - 1) {
>> +			/** update the time as current time, write to file */
>> +			fprintf(info.fp_wr, "%s%s\n", "# Generated on ",
>> +					asctime(tm_now));
>> +			continue;
>> +		}
>> +
>> +		/* to this point, no field need to update,
>> +		 *  only copy to rsp file
>> +		 */
>> +		fprintf(info.fp_wr, "%s\n", info.vec[i]);
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int
>> +parse_file_type(const char *path)
>> +{
>> +	const char *tmp = path + strlen(path) - 3;
>> +
>> +	if (strstr(tmp, REQ_FILE_PERFIX))
>> +		info.file_type = FIPS_TYPE_REQ;
>> +	else if (strstr(tmp, RSP_FILE_PERFIX))
>> +		info.file_type = FIPS_TYPE_RSP;
>> +	else if (strstr(path, FAX_FILE_PERFIX))
>> +		info.file_type = FIPS_TYPE_FAX;
>> +	else
>> +		return -EINVAL;
>> +
>> +	return 0;
>> +}
>> +
>> +int
>> +fips_test_init(const char *req_file_path, const char *rsp_file_path,
>> +		const char *device_name)
>> +{
>> +	if (strcmp(req_file_path, rsp_file_path) == 0) {
>> +		RTE_LOG(ERR, USER1, "File paths cannot be the same\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	fips_test_clear();
>> +
>> +	info.algo = FIPS_TEST_ALGO_MAX;
>> +	if (parse_file_type(req_file_path) < 0) {
>> +		RTE_LOG(ERR, USER1, "File %s type not supported\n",
>> +				req_file_path);
>> +		return -EINVAL;
>> +	}
>> +
>> +	info.fp_rd = fopen(req_file_path, "r");
>> +	if (!info.fp_rd) {
>> +		RTE_LOG(ERR, USER1, "Cannot open file %s\n", req_file_path);
>> +		return -EINVAL;
>> +	}
>> +
>> +	info.fp_wr = fopen(rsp_file_path, "w");
>> +	if (!info.fp_wr) {
>> +		RTE_LOG(ERR, USER1, "Cannot open file %s\n", rsp_file_path);
>> +		return -EINVAL;
>> +	}
>> +
>> +	info.one_line_text = calloc(1, MAX_LINE_CHAR);
>> +	if (!info.one_line_text) {
>> +		RTE_LOG(ERR, USER1, "Insufficient memory\n");
>> +		return -ENOMEM;
>> +	}
>> +
>> +	strlcpy(info.device_name, device_name, sizeof(info.device_name));
>> +
>> +	if (fips_test_parse_header() < 0) {
>> +		RTE_LOG(ERR, USER1, "Failed parsing header\n");
>> +		return -1;
>> +	}
> memory leak for calloc done above in case of error.
> Also there is no fclose in case of errors.

All memory allocated will be freed and the files are closed in the 
fips_test_clear function and is called in the end of the main function.


>> +
>> +	return 0;
>> +}
>> +
>> +void
>> +fips_test_clear(void)
>> +{
>> +	if (info.fp_rd)
>> +		fclose(info.fp_rd);
>> +	if (info.fp_wr)
>> +		fclose(info.fp_wr);
>> +	if (info.one_line_text)
>> +		free(info.one_line_text);
>> +	if (info.nb_vec_lines) {
>> +		uint32_t i;
>> +
>> +		for (i = 0; i < info.nb_vec_lines; i++)
>> +			free(info.vec[i]);
>> +	}
>> +
>> +	memset(&info, 0, sizeof(info));
>> +}
>> +
>> +int
>> +fips_test_parse_one_case(void)
>> +{
>> +	uint32_t i, j = 0;
>> +	uint32_t is_interim = 0;
>> +	int ret;
>> +
>> +	if (info.interim_callbacks) {
>> +		for (i = 0; i < info.nb_vec_lines; i++) {
>> +			for (j = 0; info.interim_callbacks[j].key != NULL; j++)
>> +				if (strstr(info.vec[i],
>> +					info.interim_callbacks[j].key)) {
> it looks interim_callback is a single structure and there is no need for
> treating as an array.
For some tests interim data could be multiple lines.
>> +					is_interim = 1;
>> +
>> +					ret = info.interim_callbacks[j].cb(
>> +						info.interim_callbacks[j].key,
>> +						info.vec[i],
>> +						info.interim_callbacks[j].val);
>> +					if (ret < 0)
>> +						return ret;
>> +				}
>> +		}
>> +	}
>> +
>> +	if (is_interim) {
>> +		for (i = 0; i < info.nb_vec_lines; i++)
>> +			fprintf(info.fp_wr, "%s\n", info.vec[i]);
>> +		fprintf(info.fp_wr, "\n");
>> +		return 1;
>> +	}
>> +
>> +	for (i = 0; i < info.nb_vec_lines; i++) {
>> +		for (j = 0; info.callbacks[j].key != NULL; j++)
>> +			if (strstr(info.vec[i], info.callbacks[j].key)) {
>> +				ret = info.callbacks[j].cb(
>> +					info.callbacks[j].key,
>> +					info.vec[i], info.callbacks[j].val);
>> +				if (ret < 0)
>> +					return ret;
>> +				break;
>> +			}
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +void
>> +fips_test_write_one_case(void)
>> +{
>> +	uint32_t i;
>> +
>> +	for (i = 0; i < info.nb_vec_lines; i++)
>> +		fprintf(info.fp_wr, "%s\n", info.vec[i]);
>> +}
>> +
>> +static int
>> +parser_read_uint64_hex(uint64_t *value, const char *p)
>> +{
>> +	char *next;
>> +	uint64_t val;
>> +
>> +	p = skip_white_spaces(p);
>> +
>> +	val = strtoul(p, &next, 16);
>> +	if (p == next)
>> +		return -EINVAL;
>> +
>> +	p = skip_white_spaces(next);
>> +	if (*p != '\0')
>> +		return -EINVAL;
>> +
>> +	*value = val;
>> +	return 0;
>> +}
>> +
>> +int
>> +parser_read_uint8_hex(uint8_t *value, const char *p)
>> +{
>> +	uint64_t val = 0;
>> +	int ret = parser_read_uint64_hex(&val, p);
>> +
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	if (val > UINT8_MAX)
>> +		return -ERANGE;
>> +
>> +	*value = val;
>> +	return 0;
>> +}
>> +
>> +int
>> +parse_uint8_known_len_hex_str(const char *key, char *src, struct fips_val *val)
>> +{
>> +	struct fips_val tmp_val = {0};
>> +	uint32_t len = val->len;
>> +	int ret;
>> +
>> +	if (len == 0) {
>> +		if (val->val != NULL) {
>> +			rte_free(val->val);
>> +			val->val = NULL;
>> +		}
>> +
>> +		return 0;
>> +	}
>> +
>> +	ret = parse_uint8_hex_str(key, src, &tmp_val);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	if (tmp_val.len == val->len) {
>> +		val->val = tmp_val.val;
>> +		return 0;
>> +	}
>> +
>> +	if (tmp_val.len < val->len) {
>> +		rte_free(tmp_val.val);
>> +		return -EINVAL;
>> +	}
>> +
>> +	val->val = rte_zmalloc(NULL, val->len, 0);
>> +	if (!val->val) {
>> +		rte_free(tmp_val.val);
>> +		memset(val, 0, sizeof(*val));
>> +		return -ENOMEM;
>> +	}
>> +
>> +	memcpy(val->val, tmp_val.val, val->len);
>> +	rte_free(tmp_val.val);
>> +
>> +	return 0;
>> +}
>> +
>> +int
>> +parse_uint8_hex_str(const char *key, char *src, struct fips_val *val)
>> +{
>> +	uint32_t len, j;
>> +
>> +	src += strlen(key);
>> +
>> +	len = strlen(src) / 2;
>> +
>> +	if (val->val) {
>> +		rte_free(val->val);
>> +		val->val = NULL;
>> +	}
>> +
>> +	val->val = rte_zmalloc(NULL, len, 0);
>> +	if (!val->val)
>> +		return -1;
> should be -ENOMEM
will change it.
>> +
>> +	for (j = 0; j < len; j++) {
>> +		char byte[3] = {src[j * 2], src[j * 2 + 1], '\0'};
>> +
>> +		if (parser_read_uint8_hex(&val->val[j], byte) < 0) {
>> +			rte_free(val->val);
>> +			memset(val, 0, sizeof(*val));
>> +			return -EINVAL;
>> +		}
>> +	}
>> +
>> +	val->len = len;
>> +
>> +	return 0;
>> +}
>> +
>> +int
>> +parser_read_uint32_val(const char *key, char *src, struct fips_val *val)
>> +{
>> +	char *data = src + strlen(key);
>> +	size_t data_len = strlen(data);
>> +	int ret;
>> +
>> +	if (data[data_len - 1] == ']') {
>> +		char *tmp_data = calloc(1, data_len + 1);
>> +
>> +		if (tmp_data == NULL)
>> +			return -ENOMEM;
>> +
>> +		strlcpy(tmp_data, data, data_len);
>> +
>> +		ret = parser_read_uint32(&val->len, tmp_data);
>> +
>> +		free(tmp_data);
>> +	} else
>> +		ret = parser_read_uint32(&val->len, data);
>> +
>> +	return ret;
>> +}
>> +
>> +int
>> +parser_read_uint32_bit_val(const char *key, char *src, struct fips_val *val)
>> +{
>> +	int ret;
>> +
>> +	ret = parser_read_uint32_val(key, src, val);
>> +
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	val->len /= 8;
>> +
>> +	return 0;
>> +}
>> +
>> +int
>> +writeback_hex_str(const char *key, char *dst, struct fips_val *val)
>> +{
>> +	char *str = dst;
>> +	uint32_t len;
>> +
>> +	str += strlen(key);
>> +
>> +	for (len = 0; len < val->len; len++)
>> +		snprintf(str + len * 2, 255, "%02x", val->val[len]);
>> +
>> +	return 0;
>> +}
>> +
>> +static int
>> +parser_read_uint64(uint64_t *value, const char *p)
>> +{
>> +	char *next;
>> +	uint64_t val;
>> +
>> +	p = skip_white_spaces(p);
>> +	if (!isdigit(*p))
>> +		return -EINVAL;
>> +
>> +	val = strtoul(p, &next, 10);
>> +	if (p == next)
>> +		return -EINVAL;
>> +
>> +	p = next;
>> +	switch (*p) {
>> +	case 'T':
>> +		val *= 1024ULL;
>> +		/* fall through */
>> +	case 'G':
>> +		val *= 1024ULL;
>> +		/* fall through */
>> +	case 'M':
>> +		val *= 1024ULL;
>> +		/* fall through */
>> +	case 'k':
>> +	case 'K':
>> +		val *= 1024ULL;
>> +		p++;
>> +		break;
>> +	}
>> +
>> +	p = skip_white_spaces(p);
>> +	if (*p != '\0')
>> +		return -EINVAL;
>> +
>> +	*value = val;
>> +	return 0;
>> +}
>> +
>> +int
>> +parser_read_uint32(uint32_t *value, char *p)
>> +{
>> +	uint64_t val = 0;
>> +	int ret = parser_read_uint64(&val, p);
>> +
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	if (val > UINT32_MAX)
>> +		return -EINVAL;
>> +
>> +	*value = val;
>> +	return 0;
>> +}
>> +
>> +void
>> +parse_write_hex_str(struct fips_val *src)
>> +{
>> +	writeback_hex_str("", info.one_line_text, src);
>> +
>> +	fprintf(info.fp_wr, "%s\n", info.one_line_text);
>> +}
>> +
>> +int
>> +update_info_vec(uint32_t count)
>> +{
>> +	const struct fips_test_callback *cb;
>> +	uint32_t i, j;
>> +
>> +	if (!info.writeback_callbacks)
>> +		return -1;
>> +
>> +	cb = &info.writeback_callbacks[0];
>> +
>> +	snprintf(info.vec[0], strlen(info.vec[0]) + 4, "%s%u", cb->key, count);
>> +
>> +	for (i = 1; i < info.nb_vec_lines; i++) {
>> +		for (j = 1; info.writeback_callbacks[j].key != NULL; j++) {
>> +			cb = &info.writeback_callbacks[j];
>> +			if (strstr(info.vec[i], cb->key)) {
>> +				cb->cb(cb->key, info.vec[i], cb->val);
>> +				break;
>> +			}
>> +		}
>> +	}
>> +
>> +	return 0;
>> +}
>> diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
>> new file mode 100644
>> index 0000000..beb6bed
>> --- /dev/null
>> +++ b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
>> @@ -0,0 +1,150 @@
>> +/* SPDX-License-Identifier: BSD-3-Clause
>> + * Copyright(c) 2018 Intel Corporation
>> + */
>> +
>> +#ifndef _CRYPTODEV_NIST_FIPS_PARSER_H_
>> +#define _CRYPTODEV_NIST_FIPS_PARSER_H_
>> +
>> +#define FIPS_PARSE_ERR(fmt, args)					\
>> +	RTE_LOG(ERR, USER1, "FIPS parse error" ## fmt ## "\n", ## args)
>> +
>> +#define ERR_MSG_SIZE		128
>> +#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 MAX_STRING_SIZE		64
>> +
>> +#define POSITIVE_TEST		0
>> +#define NEGATIVE_TEST		-1
>> +
>> +#define REQ_FILE_PERFIX		"req"
>> +#define RSP_FILE_PERFIX		"rsp"
>> +#define FAX_FILE_PERFIX		"fax"
>> +
>> +enum fips_test_algorithms {
>> +		FIPS_TEST_ALGO_MAX
>> +};
>> +
>> +enum file_types {
>> +	FIPS_TYPE_REQ = 1,
>> +	FIPS_TYPE_FAX,
>> +	FIPS_TYPE_RSP
>> +};
>> +
>> +enum fips_test_op {
>> +	FIPS_TEST_ENC_AUTH_GEN = 1,
>> +	FIPS_TEST_DEC_AUTH_VERIF,
>> +};
>> +
>> +#define MAX_LINE_PER_VECTOR            16
>> +
>> +struct fips_val {
>> +	uint8_t *val;
>> +	uint32_t len;
>> +};
>> +
>> +struct fips_test_vector {
>> +	union {
>> +		struct {
>> +			struct fips_val key;
>> +			struct fips_val digest;
>> +			struct fips_val auth_aad;
>> +			struct fips_val aad;
>> +		} cipher_auth;
>> +		struct {
>> +			struct fips_val key;
>> +			struct fips_val digest;
>> +			struct fips_val aad;
>> +		} aead;
>> +	};
>> +
>> +	struct fips_val pt;
>> +	struct fips_val ct;
>> +	struct fips_val iv;
>> +
>> +	enum rte_crypto_op_status status;
>> +};
>> +
>> +typedef int (*post_prcess_t)(struct fips_val *val);
>> +
>> +typedef int (*parse_callback_t)(const char *key, char *text,
>> +		struct fips_val *val);
>> +
>> +struct fips_test_callback {
>> +	const char *key;
>> +	parse_callback_t cb;
>> +	struct fips_val *val;
>> +};
>> +
>> +struct fips_test_interim_info {
>> +	FILE *fp_rd;
>> +	FILE *fp_wr;
>> +	enum file_types file_type;
>> +	enum fips_test_algorithms algo;
>> +	char *one_line_text;
>> +	char *vec[MAX_LINE_PER_VECTOR];
>> +	uint32_t nb_vec_lines;
>> +	//uint8_t cryptodev_id;
> remove if not needed
will do missed it.
>> +	char device_name[MAX_STRING_SIZE];
>> +
>> +	enum fips_test_op op;
>> +
>> +	const struct fips_test_callback *callbacks;
>> +	const struct fips_test_callback *interim_callbacks;
>> +	const struct fips_test_callback *writeback_callbacks;
>> +
>> +	post_prcess_t parse_writeback;
>> +	post_prcess_t kat_check;
>> +};
>> +
>> +extern struct fips_test_vector vec;
>> +extern struct fips_test_interim_info info;
>> +
>> +int
>> +fips_test_init(const char *req_file_path, const char *rsp_file_path,
>> +		const char *device_name);
>> +
>> +void
>> +fips_test_clear(void);
>> +
>> +int
>> +fips_test_fetch_one_block(void);
>> +
>> +int
>> +fips_test_parse_one_case(void);
>> +
>> +void
>> +fips_test_write_one_case(void);
>> +
>> +int
>> +parser_read_uint8_hex(uint8_t *value, const char *p);
>> +
>> +int
>> +parse_uint8_hex_str(const char *key, char *src, struct fips_val *val);
>> +
>> +int
>> +parse_uint8_known_len_hex_str(const char *key, char *src, struct fips_val *val);
>> +
>> +int
>> +parser_read_uint32_val(const char *key, char *src, struct fips_val *val);
>> +
>> +int
>> +parser_read_uint32_bit_val(const char *key, char *src, struct fips_val *val);
>> +
>> +int
>> +parser_read_uint32(uint32_t *value, char *p);
>> +
>> +int
>> +parser_read_uint32_val(const char *key, char *src, struct fips_val *val);
>> +
>> +int
>> +writeback_hex_str(const char *key, char *dst, struct fips_val *val);
>> +
>> +void
>> +parse_write_hex_str(struct fips_val *src);
>> +
>> +int
>> +update_info_vec(uint32_t count);
>> +
>> +#endif
>> diff --git a/examples/cryptodev_fips_validate/main.c b/examples/cryptodev_fips_validate/main.c
>> new file mode 100644
>> index 0000000..4f14b04
>> --- /dev/null
>> +++ b/examples/cryptodev_fips_validate/main.c
>> @@ -0,0 +1,388 @@
>> +/* SPDX-License-Identifier: BSD-3-Clause
>> + * Copyright(c) 2018 Intel Corporation
>> + */
>> +
>> +#include <sys/stat.h>
>> +#include <getopt.h>
>> +#include <dirent.h>
>> +
>> +#include <rte_cryptodev.h>
>> +#include <rte_cryptodev_pmd.h>
>> +#include <rte_mempool.h>
>> +#include <rte_mbuf.h>
>> +#include <rte_string_fns.h>
>> +
>> +#include "cryptodev_fips_validate.h"
>> +
>> +#define REQ_FILE_PATH_KEYWORD	"req-file"
>> +#define RSP_FILE_PATH_KEYWORD	"rsp-file"
>> +#define FOLDER_KEYWORD		"path-is-folder"
>> +#define CRYPTODEV_KEYWORD	"cryptodev"
>> +#define CRYPTODEV_ID_KEYWORD	"cryptodev-id"
>> +
>> +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;
>> +	uint32_t dev_id;
>> +	struct rte_mempool *mpool;
>> +	struct rte_mempool *op_pool;
>> +	struct rte_mbuf *mbuf;
>> +	struct rte_crypto_op *op;
>> +	struct rte_cryptodev_sym_session *sess;
>> +} env;
>> +
>> +static int
>> +cryptodev_fips_validate_app_int(void)
>> +{
>> +	struct rte_cryptodev_config conf = {rte_socket_id(), 1};
>> +	struct rte_cryptodev_qp_conf qp_conf = {128};
>> +	int ret;
>> +
>> +	ret = rte_cryptodev_configure(env.dev_id, &conf);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", 128, 0, 0,
>> +			UINT16_MAX, rte_socket_id());
>> +	if (!env.mpool)
>> +		return ret;
>> +
>> +	ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
>> +			rte_socket_id(), env.mpool);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	ret = -ENOMEM;
>> +
>> +	env.op_pool = rte_crypto_op_pool_create(
>> +			"FIPS_OP_POOL",
>> +			RTE_CRYPTO_OP_TYPE_SYMMETRIC,
>> +			1, 0,
>> +			16,
>> +			rte_socket_id());
>> +	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;
>> +
>> +	return 0;
>> +
>> +error_exit:
>> +	rte_mempool_free(env.mpool);
>> +	if (env.op_pool)
>> +		rte_mempool_free(env.op_pool);
>> +
>> +	return ret;
>> +}
>> +
>> +static void
>> +cryptodev_fips_validate_app_uninit(void)
>> +{
>> +	rte_pktmbuf_free(env.mbuf);
>> +	rte_crypto_op_free(env.op);
>> +	rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
>> +	rte_cryptodev_sym_session_free(env.sess);
>> +	rte_mempool_free(env.mpool);
>> +	rte_mempool_free(env.op_pool);
>> +}
>> +
>> +static int
>> +fips_test_one_file(void);
>> +
>> +static int
>> +parse_cryptodev_arg(char *arg)
>> +{
>> +	int id = rte_cryptodev_get_dev_id(arg);
>> +
>> +	if (id < 0) {
>> +		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev name %s\n",
>> +				id, arg);
>> +		return id;
>> +	}
>> +
>> +	env.dev_id = (uint32_t)id;
>> +
>> +	return 0;
>> +}
>> +
>> +static int
>> +parse_cryptodev_id_arg(char *arg)
>> +{
>> +	uint32_t cryptodev_id;
>> +
>> +	if (parser_read_uint32(&cryptodev_id, arg) < 0) {
>> +		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n",
>> +				-EINVAL, arg);
>> +		return -1;
>> +	}
>> +
>> +
>> +	if (!rte_cryptodev_pmd_is_valid_dev(cryptodev_id)) {
>> +		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n",
>> +				cryptodev_id, arg);
>> +		return -1;
>> +	}
>> +
>> +	env.dev_id = (uint32_t)cryptodev_id;
>> +
>> +	return 0;
>> +}
>> +
>> +static void
>> +cryptodev_fips_validate_usage(const char *prgname)
>> +{
>> +	printf("%s [EAL options] --\n"
>> +		"  --%s: REQUEST-FILE-PATH\n"
>> +		"  --%s: RESPONSE-FILE-PATH\n"
>> +		"  --%s: indicating both paths are folders\n"
>> +		"  --%s: CRYPTODEV-NAME\n"
>> +		"  --%s: CRYPTODEV-ID-NAME\n",
>> +		prgname, REQ_FILE_PATH_KEYWORD, RSP_FILE_PATH_KEYWORD,
>> +		FOLDER_KEYWORD, CRYPTODEV_KEYWORD, CRYPTODEV_ID_KEYWORD);
>> +}
>> +
>> +static int
>> +cryptodev_fips_validate_parse_args(int argc, char **argv)
>> +{
>> +	int opt, ret;
>> +	char *prgname = argv[0];
>> +	char **argvopt;
>> +	int option_index;
>> +	struct option lgopts[] = {
>> +			{REQ_FILE_PATH_KEYWORD, required_argument, 0, 0},
>> +			{RSP_FILE_PATH_KEYWORD, required_argument, 0, 0},
>> +			{FOLDER_KEYWORD, no_argument, 0, 0},
>> +			{CRYPTODEV_KEYWORD, required_argument, 0, 0},
>> +			{CRYPTODEV_ID_KEYWORD, required_argument, 0, 0},
>> +			{NULL, 0, 0, 0}
>> +	};
>> +
>> +	argvopt = argv;
>> +
>> +	while ((opt = getopt_long(argc, argvopt, "s:",
>> +				  lgopts, &option_index)) != EOF) {
>> +
>> +		switch (opt) {
>> +		case 0:
>> +			if (strcmp(lgopts[option_index].name,
>> +					REQ_FILE_PATH_KEYWORD) == 0)
>> +				env.req_path = optarg;
>> +			else if (strcmp(lgopts[option_index].name,
>> +					RSP_FILE_PATH_KEYWORD) == 0)
>> +				env.rsp_path = optarg;
>> +			else if (strcmp(lgopts[option_index].name,
>> +					FOLDER_KEYWORD) == 0)
>> +				env.is_path_folder = 1;
>> +			else if (strcmp(lgopts[option_index].name,
>> +					CRYPTODEV_KEYWORD) == 0) {
>> +				ret = parse_cryptodev_arg(optarg);
>> +				if (ret < 0) {
>> +					cryptodev_fips_validate_usage(prgname);
>> +					return -EINVAL;
>> +				}
>> +			} else if (strcmp(lgopts[option_index].name,
>> +					CRYPTODEV_ID_KEYWORD) == 0) {
>> +				ret = parse_cryptodev_id_arg(optarg);
>> +				if (ret < 0) {
>> +					cryptodev_fips_validate_usage(prgname);
>> +					return -EINVAL;
>> +				}
>> +			} else {
>> +				cryptodev_fips_validate_usage(prgname);
>> +				return -EINVAL;
>> +			}
>> +			break;
>> +		default:
>> +			return -1;
>> +		}
>> +	}
>> +
>> +	if (env.req_path == NULL || env.rsp_path == NULL ||
>> +			env.dev_id == UINT32_MAX) {
>> +		cryptodev_fips_validate_usage(prgname);
>> +		return -EINVAL;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +int
>> +main(int argc, char *argv[])
>> +{
>> +	int ret;
>> +
>> +	ret = rte_eal_init(argc, argv);
>> +	if (ret < 0) {
>> +		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
>> +		return -1;
>> +	}
>> +
>> +	argc -= ret;
>> +	argv += ret;
>> +
>> +	ret = cryptodev_fips_validate_parse_args(argc, argv);
>> +	if (ret < 0)
>> +		rte_exit(EXIT_FAILURE, "Failed to parse arguments!\n");
>> +
>> +	ret = cryptodev_fips_validate_app_int();
>> +	if (ret < 0) {
>> +		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
>> +		return -1;
>> +	}
>> +
>> +	if (!env.is_path_folder) {
>> +		printf("Processing file %s... ", env.req_path);
>> +
>> +		ret = fips_test_init(env.req_path, env.rsp_path,
>> +			rte_cryptodev_name_get(env.dev_id));
>> +		if (ret < 0) {
>> +			RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
>> +					ret, env.req_path);
>> +			goto exit;
>> +		}
>> +
>> +
>> +		ret = fips_test_one_file();
>> +		if (ret < 0) {
>> +			RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
>> +					ret, env.req_path);
>> +			goto exit;
>> +		}
>> +
>> +		printf("Done\n");
>> +
>> +	} else {
>> +		struct dirent *dir;
>> +		DIR *d_req, *d_rsp;
>> +		char req_path[1024];
>> +		char rsp_path[1024];
>> +
>> +		d_req = opendir(env.req_path);
>> +		if (!d_req) {
>> +			RTE_LOG(ERR, USER1, "Error %i: Path %s not exist\n",
>> +					-EINVAL, env.req_path);
>> +			goto exit;
>> +		}
>> +
>> +		d_rsp = opendir(env.rsp_path);
>> +		if (!d_rsp) {
>> +			ret = mkdir(env.rsp_path, 0700);
>> +			if (ret == 0)
>> +				d_rsp = opendir(env.rsp_path);
>> +			else {
>> +				RTE_LOG(ERR, USER1, "Error %i: Invalid %s\n",
>> +						-EINVAL, env.rsp_path);
>> +				goto exit;
>> +			}
>> +		}
>> +		closedir(d_rsp);
>> +
>> +		while ((dir = readdir(d_req)) != NULL) {
>> +			if (strstr(dir->d_name, "req") == NULL)
>> +				continue;
>> +
>> +			snprintf(req_path, 1023, "%s/%s", env.req_path,
>> +					dir->d_name);
>> +			snprintf(rsp_path, 1023, "%s/%s", env.rsp_path,
>> +					dir->d_name);
>> +			strlcpy(strstr(rsp_path, "req"), "rsp", 4);
>> +
>> +			printf("Processing file %s... ", req_path);
>> +
>> +			ret = fips_test_init(req_path, rsp_path,
>> +			rte_cryptodev_name_get(env.dev_id));
>> +			if (ret < 0) {
>> +				RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
>> +						ret, req_path);
>> +				break;
>> +			}
>> +
>> +			ret = fips_test_one_file();
>> +			if (ret < 0) {
>> +				RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
>> +						ret, req_path);
>> +				break;
>> +			}
>> +
>> +			printf("Done\n");
>> +		}
>> +
>> +		closedir(d_req);
>> +	}
>> +
>> +
>> +exit:
>> +	fips_test_clear();
>> +	cryptodev_fips_validate_app_uninit();
>> +
>> +	return ret;
>> +
>> +}
>> +
>> +static void
>> +print_test_block(void)
>> +{
>> +	uint32_t i;
>> +
>> +	for (i = 0; i < info.nb_vec_lines; i++)
>> +		printf("%s\n", info.vec[i]);
>> +
>> +	printf("\n");
>> +}
>> +
>> +static int
>> +fips_test_one_file(void)
>> +{
>> +	int fetch_ret = 0, ret;
>> +
>> +	while (fetch_ret == 0) {
>> +		fetch_ret = fips_test_fetch_one_block();
>> +		if (fetch_ret < 0) {
>> +			RTE_LOG(ERR, USER1, "Error %i: Fetch block\n",
>> +					fetch_ret);
>> +			ret = fetch_ret;
>> +			goto error_one_case;
>> +		}
>> +
>> +		if (info.nb_vec_lines == 0) {
>> +			if (fetch_ret == -EOF)
>> +				break;
>> +
>> +			fprintf(info.fp_wr, "\n");
>> +			continue;
>> +		}
>> +
>> +		ret = fips_test_parse_one_case();
>> +		switch (ret) {
>> +		case 0:
>> +			if (ret == 0)
>> +				break;
>> +			RTE_LOG(ERR, USER1, "Error %i: test block\n",
>> +					ret);
> this log is unreachable code.

The bit that is missing is being added in v2 when i was splitting the 
patch i forgot to remove this check until this was added

ret = test_ops.test();
             if (ret == 0)
                 break;
             RTE_LOG(ERR, USER1, "Error %i: test block\n",
                     ret);
             goto error_one_case;

>> +			goto error_one_case;
>> +		case 1:
>> +			break;
>> +		default:
>> +			RTE_LOG(ERR, USER1, "Error %i: Parse block\n",
>> +					ret);
>> +			goto error_one_case;
>> +		}
> do you really need this switch case here. In both the cases you are
> breaking without doing anything.
> it should be something like
> if (ret <= 0) {
>       RTE_LOG(ERR, USER1, "Error %i: Parse block\n", ret);
>       goto error_one_case;
> }

1 = test-interim data and 0 = test-data will add  a comment with more 
info inside the files of what the return cases mean

>> +
>> +		continue;
>> +error_one_case:
>> +		print_test_block();
>> +	}
>> +
>> +	fips_test_clear();
>> +
>> +}
>> diff --git a/examples/cryptodev_fips_validate/meson.build b/examples/cryptodev_fips_validate/meson.build
>> new file mode 100644
>> index 0000000..f44043c
>> --- /dev/null
>> +++ b/examples/cryptodev_fips_validate/meson.build
>> @@ -0,0 +1,14 @@
>> +# SPDX-License-Identifier: BSD-3-Clause
>> +# Copyright(c) 2018 Intel Corporation
>> +
>> +# meson file, for building this example as part of a main DPDK build.
>> +#
>> +# To build this example as a standalone application with an already-installed
>> +# DPDK instance, use 'make'
>> +
>> +deps += ['cryptodev']
>> +allow_experimental_apis = true
>> +sources = files(
>> +	'cryptodev_fips_parse_validate.c',
>> +	'main.c'
>> +)

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

* Re: [dpdk-dev] [PATCH v5 2/8] examples/cryptodev_fips_validate: add aes parser and enablement for test types
  2018-10-24 12:37     ` Akhil Goyal
@ 2018-10-24 14:18       ` Marko Kovacevic
  0 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-24 14:18 UTC (permalink / raw)
  To: Akhil Goyal, dev; +Cc: roy.fan.zhang, arkadiuszx.kusztal


On 24/10/2018 13:37, Akhil Goyal wrote:
>
> On 10/17/2018 6:19 PM, Marko Kovacevic wrote:
>> diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
>> index beb6bed..5ac858d 100644
>> --- a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
>> +++ b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
>> @@ -23,6 +23,7 @@
>>    #define FAX_FILE_PERFIX		"fax"
>>    
>>    enum fips_test_algorithms {
>> +		FIPS_TEST_ALGO_AES = 0,
>>    		FIPS_TEST_ALGO_MAX
>>    };
>>    
>> @@ -77,6 +78,21 @@ struct fips_test_callback {
>>    	struct fips_val *val;
>>    };
>>    
>> +enum fips_aesavs_test_types {
>> +	AESAVS_TYPE_GFXBOX = 0,
>> +	AESAVS_TYPE_KEYSBOX,
>> +	AESAVS_TYPE_VARKEY,
>> +	AESAVS_TYPE_VARTXT,
>> +	AESAVS_TYPE_MMT,
>> +	AESAVS_TYPE_MCT,
>> +};
> It would be better to start the enums from 1. Consider a case when an
> uninitialized/unsupported type is accidentally used and it would be
> treated as AES and would be processed accordingly.
sure ill change that

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

* Re: [dpdk-dev] [PATCH v5 1/8] examples/cryptodev_fips_validate: add fips validation into examples
  2018-10-24 14:17       ` Marko Kovacevic
@ 2018-10-24 14:36         ` Akhil Goyal
  2018-10-24 15:13           ` Marko Kovacevic
  0 siblings, 1 reply; 52+ messages in thread
From: Akhil Goyal @ 2018-10-24 14:36 UTC (permalink / raw)
  To: Marko Kovacevic, dev; +Cc: roy.fan.zhang, arkadiuszx.kusztal



On 10/24/2018 7:47 PM, Marko Kovacevic wrote:
>
> On 24/10/2018 13:13, Akhil Goyal wrote:
>>
>> On 10/17/2018 6:19 PM, Marko Kovacevic wrote:
snip [..]
>
>>>
>>> +int
>>> +fips_test_parse_one_case(void)
>>> +{
>>> +    uint32_t i, j = 0;
>>> +    uint32_t is_interim = 0;
>>> +    int ret;
>>> +
>>> +    if (info.interim_callbacks) {
>>> +        for (i = 0; i < info.nb_vec_lines; i++) {
>>> +            for (j = 0; info.interim_callbacks[j].key != NULL; j++)
>>> +                if (strstr(info.vec[i],
>>> +                    info.interim_callbacks[j].key)) {
>> it looks interim_callback is a single structure and there is no need for
>> treating as an array.
> For some tests interim data could be multiple lines.
here you are not incrementing j, which means you are not using the other 
ones. Also I cannot see it getting incremented in this function in rest 
of the patches.


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

* Re: [dpdk-dev] [PATCH v5 1/8] examples/cryptodev_fips_validate: add fips validation into examples
  2018-10-24 14:36         ` Akhil Goyal
@ 2018-10-24 15:13           ` Marko Kovacevic
  0 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-24 15:13 UTC (permalink / raw)
  To: Akhil Goyal, dev; +Cc: roy.fan.zhang, arkadiuszx.kusztal


On 24/10/2018 15:36, Akhil Goyal wrote:
>
> On 10/24/2018 7:47 PM, Marko Kovacevic wrote:
>> On 24/10/2018 13:13, Akhil Goyal wrote:
>>> On 10/17/2018 6:19 PM, Marko Kovacevic wrote:
> snip [..]
>>>> +int
>>>> +fips_test_parse_one_case(void)
>>>> +{
>>>> +    uint32_t i, j = 0;
>>>> +    uint32_t is_interim = 0;
>>>> +    int ret;
>>>> +
>>>> +    if (info.interim_callbacks) {
>>>> +        for (i = 0; i < info.nb_vec_lines; i++) {
>>>> +            for (j = 0; info.interim_callbacks[j].key != NULL; j++)
>>>> +                if (strstr(info.vec[i],
>>>> +                    info.interim_callbacks[j].key)) {
>>> it looks interim_callback is a single structure and there is no need for
>>> treating as an array.
>> For some tests interim data could be multiple lines.
> here you are not incrementing j, which means you are not using the other
> ones. Also I cannot see it getting incremented in this function in rest
> of the patches.

   for (j = 0; info.interim_callbacks[j].key != NULL; j++)
j is incremented as shown in the above line

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

* [dpdk-dev] [PATCH v6 0/8] FIPS validation capability
  2018-10-17 12:49 ` [dpdk-dev] [PATCH v5 " Marko Kovacevic
                     ` (8 preceding siblings ...)
  2018-10-24 11:42   ` [dpdk-dev] [PATCH v5 0/8] FIPS validation capability Akhil Goyal
@ 2018-10-26 11:07   ` Marko Kovacevic
  2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 1/8] examples/fips_validation: add cryptodev fips compliant application Marko Kovacevic
                       ` (9 more replies)
  9 siblings, 10 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-26 11:07 UTC (permalink / raw)
  To: akhil.goyal; +Cc: dev, roy.fan.zhang, arkadiuszx.kusztal, Kovacevic, Marko

From: "Kovacevic, Marko" <marko.kovacevic@intel.com>

This sample application is made for the purpose so that users of DPDK
who wish to get FIPS certification for their platforms, this sample app enables
users to parse test vectors that is gotten from NIST and be able to get
a generated response file which they can then verify and be sure their
system will pass FIPS certification.


Marko Kovacevic (8):
v6:
  - Added MAINTAINER file into different patch
  - Udpated documentation
  - Changed app name and file location
  - Fixed memory leak in TDES
  - Changed patch titles
  - Made other changes from comments
v5:
  - Changed patch titles
  - Added MAINTAINERS File
  - Removed bus_pci Dependency
  - Updated documentation
  - Changed app name
v4:
- Added Limitation
- Changed TDES BLOCK SIZE from 16 -> 8
  as DES block size is 64bits (main.c)
v3:
- Fixed a no-testing bug
- Fixed some code style issue

v2:
- Refactor the code.
- Move the code from test to sample applcation

Kovacevic, Marko (8):
  examples/fips_validation: add cryptodev fips compliant application
  examples/fips_validation: support AES parsing
  examples/fips_validation: support HMAC parsing
  examples/fips_validation: support TDES parsing
  examples/fips_validation: support GCM parsing
  examples/fips_validation: support CMAC parsing
  examples/fips_validation: support CCM parsing
  doc: add fips validation application guide

 MAINTAINERS                                     |    4 +
 doc/guides/rel_notes/release_18_11.rst          |    5 +
 doc/guides/sample_app_ug/fips_validation.rst    |  132 +++
 doc/guides/sample_app_ug/index.rst              |    1 +
 examples/fips_validation/Makefile               |   75 ++
 examples/fips_validation/fips_validation.c      |  593 +++++++++++
 examples/fips_validation/fips_validation.h      |  233 +++++
 examples/fips_validation/fips_validation_aes.c  |  188 ++++
 examples/fips_validation/fips_validation_ccm.c  |  272 +++++
 examples/fips_validation/fips_validation_cmac.c |  116 +++
 examples/fips_validation/fips_validation_gcm.c  |  125 +++
 examples/fips_validation/fips_validation_hmac.c |  105 ++
 examples/fips_validation/fips_validation_tdes.c |  264 +++++
 examples/fips_validation/main.c                 | 1221 +++++++++++++++++++++++
 examples/fips_validation/meson.build            |   20 +
 15 files changed, 3354 insertions(+)
 create mode 100644 doc/guides/sample_app_ug/fips_validation.rst
 create mode 100644 examples/fips_validation/Makefile
 create mode 100644 examples/fips_validation/fips_validation.c
 create mode 100644 examples/fips_validation/fips_validation.h
 create mode 100644 examples/fips_validation/fips_validation_aes.c
 create mode 100644 examples/fips_validation/fips_validation_ccm.c
 create mode 100644 examples/fips_validation/fips_validation_cmac.c
 create mode 100644 examples/fips_validation/fips_validation_gcm.c
 create mode 100644 examples/fips_validation/fips_validation_hmac.c
 create mode 100644 examples/fips_validation/fips_validation_tdes.c
 create mode 100644 examples/fips_validation/main.c
 create mode 100644 examples/fips_validation/meson.build

-- 
2.9.5

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

* [dpdk-dev] [PATCH v6 1/8] examples/fips_validation: add cryptodev fips compliant application
  2018-10-26 11:07   ` [dpdk-dev] [PATCH v6 " Marko Kovacevic
@ 2018-10-26 11:07     ` Marko Kovacevic
  2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 2/8] examples/fips_validation: support AES parsing Marko Kovacevic
                       ` (8 subsequent siblings)
  9 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-26 11:07 UTC (permalink / raw)
  To: akhil.goyal; +Cc: dev, roy.fan.zhang, arkadiuszx.kusztal, Kovacevic, Marko

From: "Kovacevic, Marko" <marko.kovacevic@intel.com>

Added FIPS application into the examples to allow
users to use a simple sample app to validate
their systems and be able to get FIPS certification.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 MAINTAINERS                                |   4 +
 examples/fips_validation/Makefile          |  69 ++++
 examples/fips_validation/fips_validation.c | 562 +++++++++++++++++++++++++++++
 examples/fips_validation/fips_validation.h | 149 ++++++++
 examples/fips_validation/main.c            | 388 ++++++++++++++++++++
 examples/fips_validation/meson.build       |  14 +
 6 files changed, 1186 insertions(+)
 create mode 100644 examples/fips_validation/Makefile
 create mode 100644 examples/fips_validation/fips_validation.c
 create mode 100644 examples/fips_validation/fips_validation.h
 create mode 100644 examples/fips_validation/main.c
 create mode 100644 examples/fips_validation/meson.build

diff --git a/MAINTAINERS b/MAINTAINERS
index b220479..8e0d3a5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1336,3 +1336,7 @@ F: examples/tep_termination/
 F: examples/vmdq/
 F: examples/vmdq_dcb/
 F: doc/guides/sample_app_ug/vmdq_dcb_forwarding.rst
+
+M: Marko Kovacevic <marko.kovacevic@intel.com>
+F: examples/fips_validation
+F: doc/guides/sample_app_ug/fips_validation.rst
diff --git a/examples/fips_validation/Makefile b/examples/fips_validation/Makefile
new file mode 100644
index 0000000..59d56c7
--- /dev/null
+++ b/examples/fips_validation/Makefile
@@ -0,0 +1,69 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Intel Corporation
+
+# binary name
+APP = fips_validation
+
+# all source are stored in SRCS-y
+SRCS-y := fips_validation.c
+SRCS-y += main.c
+
+# Build using pkg-config variables if possible
+$(shell pkg-config --exists libdpdk)
+ifeq ($(.SHELLSTATUS),0)
+
+all: shared
+.PHONY: shared static
+shared: build/$(APP)-shared
+	ln -sf $(APP)-shared build/$(APP)
+static: build/$(APP)-static
+	ln -sf $(APP)-static build/$(APP)
+
+PC_FILE := $(shell pkg-config --path libdpdk)
+CFLAGS += -O3 $(shell pkg-config --cflags libdpdk)
+LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk)
+LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk)
+
+build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
+	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
+
+build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build
+	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC)
+
+build:
+	@mkdir -p $@
+
+.PHONY: clean
+clean:
+	rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared
+	rmdir --ignore-fail-on-non-empty build
+
+else
+
+ifeq ($(RTE_SDK),)
+$(error "Please define RTE_SDK environment variable")
+endif
+
+# Default target, can be overridden by command line or environment
+RTE_TARGET ?= x86_64-native-linuxapp-gcc
+
+INC += $(sort $(wildcard *.h))
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+CFLAGS += $(WERROR_FLAGS)
+
+# workaround for a gcc bug with noreturn attribute
+# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603
+ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
+CFLAGS_main.o += -Wno-return-type
+endif
+
+CFLAGS += -DALLOW_EXPERIMENTAL_API
+CFLAGS += -I$(SRCDIR)
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+include $(RTE_SDK)/mk/rte.extapp.mk
+
+endif
diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
new file mode 100644
index 0000000..8ed15f4
--- /dev/null
+++ b/examples/fips_validation/fips_validation.c
@@ -0,0 +1,562 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <rte_string_fns.h>
+#include <rte_cryptodev.h>
+#include <rte_malloc.h>
+
+#include "fips_validation.h"
+
+#define skip_white_spaces(pos)			\
+({						\
+	__typeof__(pos) _p = (pos);		\
+	for ( ; isspace(*_p); _p++)		\
+		;				\
+	_p;					\
+})
+
+static int
+get_file_line(void)
+{
+	FILE *fp = info.fp_rd;
+	char *line = info.one_line_text;
+	char c;
+	uint32_t loc = 0;
+
+	memset(line, 0, MAX_LINE_CHAR);
+	while ((c = fgetc(fp)) != EOF) {
+		if (loc >= MAX_LINE_CHAR - 1)
+			return -ENOMEM;
+		if (c == '\n')
+			return 0;
+		line[loc++] = c;
+	}
+
+	if (c == EOF)
+		return -EOF;
+
+	return 0;
+}
+
+int
+fips_test_fetch_one_block(void)
+{
+	size_t size;
+	int ret = 0;
+	uint32_t i;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		free(info.vec[i]);
+		info.vec[i] = NULL;
+	}
+
+	i = 0;
+	do {
+		if (i >= MAX_LINE_PER_VECTOR) {
+			ret = -ENOMEM;
+			goto error_exit;
+		}
+
+		ret = get_file_line();
+		size = strlen(info.one_line_text);
+		if (size == 0)
+			break;
+
+		info.vec[i] = calloc(1, size + 5);
+		if (info.vec[i] == NULL)
+			goto error_exit;
+
+		strlcpy(info.vec[i], info.one_line_text, size + 1);
+		i++;
+	} while (ret == 0);
+
+	info.nb_vec_lines = i;
+
+	return ret;
+
+error_exit:
+	for (i = 0; i < MAX_LINE_PER_VECTOR; i++)
+		if (info.vec[i] != NULL) {
+			free(info.vec[i]);
+			info.vec[i] = NULL;
+		}
+
+	info.nb_vec_lines = 0;
+
+	return -ENOMEM;
+}
+
+static int
+fips_test_parse_header(void)
+{
+	uint32_t i;
+	char *tmp;
+	int ret;
+	time_t t = time(NULL);
+	struct tm *tm_now = localtime(&t);
+
+	ret = fips_test_fetch_one_block();
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+
+		tmp = strstr(info.vec[i], "# Config info for ");
+		if (tmp != NULL) {
+			fprintf(info.fp_wr, "%s%s\n", "# Config info for DPDK Cryptodev ",
+					info.device_name);
+			continue;
+		}
+
+		tmp = strstr(info.vec[i], "#  HMAC information for ");
+		if (tmp != NULL) {
+			fprintf(info.fp_wr, "%s%s\n", "#  HMAC information for "
+				"DPDK Cryptodev ",
+				info.device_name);
+			continue;
+		}
+
+		tmp = strstr(info.vec[i], "# Config Info for : ");
+		if (tmp != NULL) {
+
+			fprintf(info.fp_wr, "%s%s\n", "# Config Info for DPDK Cryptodev : ",
+					info.device_name);
+			continue;
+		}
+
+		tmp = strstr(info.vec[i], "# information for ");
+		if (tmp != NULL) {
+
+			char tmp_output[128] = {0};
+
+			strlcpy(tmp_output, info.vec[i], tmp - info.vec[i] + 1);
+
+			fprintf(info.fp_wr, "%s%s%s\n", tmp_output,
+					"information for DPDK Cryptodev ",
+					info.device_name);
+			continue;
+		}
+
+		tmp = strstr(info.vec[i], " test information for ");
+		if (tmp != NULL) {
+			char tmp_output[128] = {0};
+
+			strlcpy(tmp_output, info.vec[i], tmp - info.vec[i] + 1);
+
+			fprintf(info.fp_wr, "%s%s%s\n", tmp_output,
+					"test information for DPDK Cryptodev ",
+					info.device_name);
+			continue;
+		}
+
+		if (i == info.nb_vec_lines - 1) {
+			/** update the time as current time, write to file */
+			fprintf(info.fp_wr, "%s%s\n", "# Generated on ",
+					asctime(tm_now));
+			continue;
+		}
+
+		/* to this point, no field need to update,
+		 *  only copy to rsp file
+		 */
+		fprintf(info.fp_wr, "%s\n", info.vec[i]);
+	}
+
+	return 0;
+}
+
+static int
+parse_file_type(const char *path)
+{
+	const char *tmp = path + strlen(path) - 3;
+
+	if (strstr(tmp, REQ_FILE_PERFIX))
+		info.file_type = FIPS_TYPE_REQ;
+	else if (strstr(tmp, RSP_FILE_PERFIX))
+		info.file_type = FIPS_TYPE_RSP;
+	else if (strstr(path, FAX_FILE_PERFIX))
+		info.file_type = FIPS_TYPE_FAX;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+int
+fips_test_init(const char *req_file_path, const char *rsp_file_path,
+		const char *device_name)
+{
+	if (strcmp(req_file_path, rsp_file_path) == 0) {
+		RTE_LOG(ERR, USER1, "File paths cannot be the same\n");
+		return -EINVAL;
+	}
+
+	fips_test_clear();
+
+	info.algo = FIPS_TEST_ALGO_MAX;
+	if (parse_file_type(req_file_path) < 0) {
+		RTE_LOG(ERR, USER1, "File %s type not supported\n",
+				req_file_path);
+		return -EINVAL;
+	}
+
+	info.fp_rd = fopen(req_file_path, "r");
+	if (!info.fp_rd) {
+		RTE_LOG(ERR, USER1, "Cannot open file %s\n", req_file_path);
+		return -EINVAL;
+	}
+
+	info.fp_wr = fopen(rsp_file_path, "w");
+	if (!info.fp_wr) {
+		RTE_LOG(ERR, USER1, "Cannot open file %s\n", rsp_file_path);
+		return -EINVAL;
+	}
+
+	info.one_line_text = calloc(1, MAX_LINE_CHAR);
+	if (!info.one_line_text) {
+		RTE_LOG(ERR, USER1, "Insufficient memory\n");
+		return -ENOMEM;
+	}
+
+	strlcpy(info.device_name, device_name, sizeof(info.device_name));
+
+	if (fips_test_parse_header() < 0) {
+		RTE_LOG(ERR, USER1, "Failed parsing header\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+void
+fips_test_clear(void)
+{
+	if (info.fp_rd)
+		fclose(info.fp_rd);
+	if (info.fp_wr)
+		fclose(info.fp_wr);
+	if (info.one_line_text)
+		free(info.one_line_text);
+	if (info.nb_vec_lines) {
+		uint32_t i;
+
+		for (i = 0; i < info.nb_vec_lines; i++)
+			free(info.vec[i]);
+	}
+
+	memset(&info, 0, sizeof(info));
+}
+
+int
+fips_test_parse_one_case(void)
+{
+	uint32_t i, j = 0;
+	uint32_t is_interim = 0;
+	int ret;
+
+	if (info.interim_callbacks) {
+		for (i = 0; i < info.nb_vec_lines; i++) {
+			for (j = 0; info.interim_callbacks[j].key != NULL; j++)
+				if (strstr(info.vec[i],
+					info.interim_callbacks[j].key)) {
+					is_interim = 1;
+
+					ret = info.interim_callbacks[j].cb(
+						info.interim_callbacks[j].key,
+						info.vec[i],
+						info.interim_callbacks[j].val);
+					if (ret < 0)
+						return ret;
+				}
+		}
+	}
+
+	if (is_interim) {
+		for (i = 0; i < info.nb_vec_lines; i++)
+			fprintf(info.fp_wr, "%s\n", info.vec[i]);
+		fprintf(info.fp_wr, "\n");
+		return 1;
+	}
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		for (j = 0; info.callbacks[j].key != NULL; j++)
+			if (strstr(info.vec[i], info.callbacks[j].key)) {
+				ret = info.callbacks[j].cb(
+					info.callbacks[j].key,
+					info.vec[i], info.callbacks[j].val);
+				if (ret < 0)
+					return ret;
+				break;
+			}
+	}
+
+	return 0;
+}
+
+void
+fips_test_write_one_case(void)
+{
+	uint32_t i;
+
+	for (i = 0; i < info.nb_vec_lines; i++)
+		fprintf(info.fp_wr, "%s\n", info.vec[i]);
+}
+
+static int
+parser_read_uint64_hex(uint64_t *value, const char *p)
+{
+	char *next;
+	uint64_t val;
+
+	p = skip_white_spaces(p);
+
+	val = strtoul(p, &next, 16);
+	if (p == next)
+		return -EINVAL;
+
+	p = skip_white_spaces(next);
+	if (*p != '\0')
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
+int
+parser_read_uint8_hex(uint8_t *value, const char *p)
+{
+	uint64_t val = 0;
+	int ret = parser_read_uint64_hex(&val, p);
+
+	if (ret < 0)
+		return ret;
+
+	if (val > UINT8_MAX)
+		return -ERANGE;
+
+	*value = val;
+	return 0;
+}
+
+int
+parse_uint8_known_len_hex_str(const char *key, char *src, struct fips_val *val)
+{
+	struct fips_val tmp_val = {0};
+	uint32_t len = val->len;
+	int ret;
+
+	if (len == 0) {
+		if (val->val != NULL) {
+			rte_free(val->val);
+			val->val = NULL;
+		}
+
+		return 0;
+	}
+
+	ret = parse_uint8_hex_str(key, src, &tmp_val);
+	if (ret < 0)
+		return ret;
+
+	if (tmp_val.len == val->len) {
+		val->val = tmp_val.val;
+		return 0;
+	}
+
+	if (tmp_val.len < val->len) {
+		rte_free(tmp_val.val);
+		return -EINVAL;
+	}
+
+	val->val = rte_zmalloc(NULL, val->len, 0);
+	if (!val->val) {
+		rte_free(tmp_val.val);
+		memset(val, 0, sizeof(*val));
+		return -ENOMEM;
+	}
+
+	memcpy(val->val, tmp_val.val, val->len);
+	rte_free(tmp_val.val);
+
+	return 0;
+}
+
+int
+parse_uint8_hex_str(const char *key, char *src, struct fips_val *val)
+{
+	uint32_t len, j;
+
+	src += strlen(key);
+
+	len = strlen(src) / 2;
+
+	if (val->val) {
+		rte_free(val->val);
+		val->val = NULL;
+	}
+
+	val->val = rte_zmalloc(NULL, len, 0);
+	if (!val->val)
+		return -ENOMEM;
+
+	for (j = 0; j < len; j++) {
+		char byte[3] = {src[j * 2], src[j * 2 + 1], '\0'};
+
+		if (parser_read_uint8_hex(&val->val[j], byte) < 0) {
+			rte_free(val->val);
+			memset(val, 0, sizeof(*val));
+			return -EINVAL;
+		}
+	}
+
+	val->len = len;
+
+	return 0;
+}
+
+int
+parser_read_uint32_val(const char *key, char *src, struct fips_val *val)
+{
+	char *data = src + strlen(key);
+	size_t data_len = strlen(data);
+	int ret;
+
+	if (data[data_len - 1] == ']') {
+		char *tmp_data = calloc(1, data_len + 1);
+
+		if (tmp_data == NULL)
+			return -ENOMEM;
+
+		strlcpy(tmp_data, data, data_len);
+
+		ret = parser_read_uint32(&val->len, tmp_data);
+
+		free(tmp_data);
+	} else
+		ret = parser_read_uint32(&val->len, data);
+
+	return ret;
+}
+
+int
+parser_read_uint32_bit_val(const char *key, char *src, struct fips_val *val)
+{
+	int ret;
+
+	ret = parser_read_uint32_val(key, src, val);
+
+	if (ret < 0)
+		return ret;
+
+	val->len /= 8;
+
+	return 0;
+}
+
+int
+writeback_hex_str(const char *key, char *dst, struct fips_val *val)
+{
+	char *str = dst;
+	uint32_t len;
+
+	str += strlen(key);
+
+	for (len = 0; len < val->len; len++)
+		snprintf(str + len * 2, 255, "%02x", val->val[len]);
+
+	return 0;
+}
+
+static int
+parser_read_uint64(uint64_t *value, const char *p)
+{
+	char *next;
+	uint64_t val;
+
+	p = skip_white_spaces(p);
+	if (!isdigit(*p))
+		return -EINVAL;
+
+	val = strtoul(p, &next, 10);
+	if (p == next)
+		return -EINVAL;
+
+	p = next;
+	switch (*p) {
+	case 'T':
+		val *= 1024ULL;
+		/* fall through */
+	case 'G':
+		val *= 1024ULL;
+		/* fall through */
+	case 'M':
+		val *= 1024ULL;
+		/* fall through */
+	case 'k':
+	case 'K':
+		val *= 1024ULL;
+		p++;
+		break;
+	}
+
+	p = skip_white_spaces(p);
+	if (*p != '\0')
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
+int
+parser_read_uint32(uint32_t *value, char *p)
+{
+	uint64_t val = 0;
+	int ret = parser_read_uint64(&val, p);
+
+	if (ret < 0)
+		return ret;
+
+	if (val > UINT32_MAX)
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
+void
+parse_write_hex_str(struct fips_val *src)
+{
+	writeback_hex_str("", info.one_line_text, src);
+
+	fprintf(info.fp_wr, "%s\n", info.one_line_text);
+}
+
+int
+update_info_vec(uint32_t count)
+{
+	const struct fips_test_callback *cb;
+	uint32_t i, j;
+
+	if (!info.writeback_callbacks)
+		return -1;
+
+	cb = &info.writeback_callbacks[0];
+
+	snprintf(info.vec[0], strlen(info.vec[0]) + 4, "%s%u", cb->key, count);
+
+	for (i = 1; i < info.nb_vec_lines; i++) {
+		for (j = 1; info.writeback_callbacks[j].key != NULL; j++) {
+			cb = &info.writeback_callbacks[j];
+			if (strstr(info.vec[i], cb->key)) {
+				cb->cb(cb->key, info.vec[i], cb->val);
+				break;
+			}
+		}
+	}
+
+	return 0;
+}
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
new file mode 100644
index 0000000..dd3bc09
--- /dev/null
+++ b/examples/fips_validation/fips_validation.h
@@ -0,0 +1,149 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _FIPS_VALIDATION_H_
+#define _FIPS_VALIDATION_H_
+
+#define FIPS_PARSE_ERR(fmt, args)					\
+	RTE_LOG(ERR, USER1, "FIPS parse error" ## fmt ## "\n", ## args)
+
+#define ERR_MSG_SIZE		128
+#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 MAX_STRING_SIZE		64
+
+#define POSITIVE_TEST		0
+#define NEGATIVE_TEST		-1
+
+#define REQ_FILE_PERFIX		"req"
+#define RSP_FILE_PERFIX		"rsp"
+#define FAX_FILE_PERFIX		"fax"
+
+enum fips_test_algorithms {
+		FIPS_TEST_ALGO_MAX
+};
+
+enum file_types {
+	FIPS_TYPE_REQ = 1,
+	FIPS_TYPE_FAX,
+	FIPS_TYPE_RSP
+};
+
+enum fips_test_op {
+	FIPS_TEST_ENC_AUTH_GEN = 1,
+	FIPS_TEST_DEC_AUTH_VERIF,
+};
+
+#define MAX_LINE_PER_VECTOR            16
+
+struct fips_val {
+	uint8_t *val;
+	uint32_t len;
+};
+
+struct fips_test_vector {
+	union {
+		struct {
+			struct fips_val key;
+			struct fips_val digest;
+			struct fips_val auth_aad;
+			struct fips_val aad;
+		} cipher_auth;
+		struct {
+			struct fips_val key;
+			struct fips_val digest;
+			struct fips_val aad;
+		} aead;
+	};
+
+	struct fips_val pt;
+	struct fips_val ct;
+	struct fips_val iv;
+
+	enum rte_crypto_op_status status;
+};
+
+typedef int (*post_prcess_t)(struct fips_val *val);
+
+typedef int (*parse_callback_t)(const char *key, char *text,
+		struct fips_val *val);
+
+struct fips_test_callback {
+	const char *key;
+	parse_callback_t cb;
+	struct fips_val *val;
+};
+
+struct fips_test_interim_info {
+	FILE *fp_rd;
+	FILE *fp_wr;
+	enum file_types file_type;
+	enum fips_test_algorithms algo;
+	char *one_line_text;
+	char *vec[MAX_LINE_PER_VECTOR];
+	uint32_t nb_vec_lines;
+	char device_name[MAX_STRING_SIZE];
+
+	enum fips_test_op op;
+
+	const struct fips_test_callback *callbacks;
+	const struct fips_test_callback *interim_callbacks;
+	const struct fips_test_callback *writeback_callbacks;
+
+	post_prcess_t parse_writeback;
+	post_prcess_t kat_check;
+};
+
+extern struct fips_test_vector vec;
+extern struct fips_test_interim_info info;
+
+int
+fips_test_init(const char *req_file_path, const char *rsp_file_path,
+		const char *device_name);
+
+void
+fips_test_clear(void);
+
+int
+fips_test_fetch_one_block(void);
+
+int
+fips_test_parse_one_case(void);
+
+void
+fips_test_write_one_case(void);
+
+int
+parser_read_uint8_hex(uint8_t *value, const char *p);
+
+int
+parse_uint8_hex_str(const char *key, char *src, struct fips_val *val);
+
+int
+parse_uint8_known_len_hex_str(const char *key, char *src, struct fips_val *val);
+
+int
+parser_read_uint32_val(const char *key, char *src, struct fips_val *val);
+
+int
+parser_read_uint32_bit_val(const char *key, char *src, struct fips_val *val);
+
+int
+parser_read_uint32(uint32_t *value, char *p);
+
+int
+parser_read_uint32_val(const char *key, char *src, struct fips_val *val);
+
+int
+writeback_hex_str(const char *key, char *dst, struct fips_val *val);
+
+void
+parse_write_hex_str(struct fips_val *src);
+
+int
+update_info_vec(uint32_t count);
+
+#endif
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
new file mode 100644
index 0000000..7083462
--- /dev/null
+++ b/examples/fips_validation/main.c
@@ -0,0 +1,388 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <sys/stat.h>
+#include <getopt.h>
+#include <dirent.h>
+
+#include <rte_cryptodev.h>
+#include <rte_cryptodev_pmd.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_string_fns.h>
+
+#include "fips_validation.h"
+
+#define REQ_FILE_PATH_KEYWORD	"req-file"
+#define RSP_FILE_PATH_KEYWORD	"rsp-file"
+#define FOLDER_KEYWORD		"path-is-folder"
+#define CRYPTODEV_KEYWORD	"cryptodev"
+#define CRYPTODEV_ID_KEYWORD	"cryptodev-id"
+
+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;
+	uint32_t dev_id;
+	struct rte_mempool *mpool;
+	struct rte_mempool *op_pool;
+	struct rte_mbuf *mbuf;
+	struct rte_crypto_op *op;
+	struct rte_cryptodev_sym_session *sess;
+} env;
+
+static int
+cryptodev_fips_validate_app_int(void)
+{
+	struct rte_cryptodev_config conf = {rte_socket_id(), 1};
+	struct rte_cryptodev_qp_conf qp_conf = {128};
+	int ret;
+
+	ret = rte_cryptodev_configure(env.dev_id, &conf);
+	if (ret < 0)
+		return ret;
+
+	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", 128, 0, 0,
+			UINT16_MAX, rte_socket_id());
+	if (!env.mpool)
+		return ret;
+
+	ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
+			rte_socket_id(), env.mpool);
+	if (ret < 0)
+		return ret;
+
+	ret = -ENOMEM;
+
+	env.op_pool = rte_crypto_op_pool_create(
+			"FIPS_OP_POOL",
+			RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+			1, 0,
+			16,
+			rte_socket_id());
+	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;
+
+	return 0;
+
+error_exit:
+	rte_mempool_free(env.mpool);
+	if (env.op_pool)
+		rte_mempool_free(env.op_pool);
+
+	return ret;
+}
+
+static void
+cryptodev_fips_validate_app_uninit(void)
+{
+	rte_pktmbuf_free(env.mbuf);
+	rte_crypto_op_free(env.op);
+	rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
+	rte_cryptodev_sym_session_free(env.sess);
+	rte_mempool_free(env.mpool);
+	rte_mempool_free(env.op_pool);
+}
+
+static int
+fips_test_one_file(void);
+
+static int
+parse_cryptodev_arg(char *arg)
+{
+	int id = rte_cryptodev_get_dev_id(arg);
+
+	if (id < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev name %s\n",
+				id, arg);
+		return id;
+	}
+
+	env.dev_id = (uint32_t)id;
+
+	return 0;
+}
+
+static int
+parse_cryptodev_id_arg(char *arg)
+{
+	uint32_t cryptodev_id;
+
+	if (parser_read_uint32(&cryptodev_id, arg) < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n",
+				-EINVAL, arg);
+		return -1;
+	}
+
+
+	if (!rte_cryptodev_pmd_is_valid_dev(cryptodev_id)) {
+		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n",
+				cryptodev_id, arg);
+		return -1;
+	}
+
+	env.dev_id = (uint32_t)cryptodev_id;
+
+	return 0;
+}
+
+static void
+cryptodev_fips_validate_usage(const char *prgname)
+{
+	printf("%s [EAL options] --\n"
+		"  --%s: REQUEST-FILE-PATH\n"
+		"  --%s: RESPONSE-FILE-PATH\n"
+		"  --%s: indicating both paths are folders\n"
+		"  --%s: CRYPTODEV-NAME\n"
+		"  --%s: CRYPTODEV-ID-NAME\n",
+		prgname, REQ_FILE_PATH_KEYWORD, RSP_FILE_PATH_KEYWORD,
+		FOLDER_KEYWORD, CRYPTODEV_KEYWORD, CRYPTODEV_ID_KEYWORD);
+}
+
+static int
+cryptodev_fips_validate_parse_args(int argc, char **argv)
+{
+	int opt, ret;
+	char *prgname = argv[0];
+	char **argvopt;
+	int option_index;
+	struct option lgopts[] = {
+			{REQ_FILE_PATH_KEYWORD, required_argument, 0, 0},
+			{RSP_FILE_PATH_KEYWORD, required_argument, 0, 0},
+			{FOLDER_KEYWORD, no_argument, 0, 0},
+			{CRYPTODEV_KEYWORD, required_argument, 0, 0},
+			{CRYPTODEV_ID_KEYWORD, required_argument, 0, 0},
+			{NULL, 0, 0, 0}
+	};
+
+	argvopt = argv;
+
+	while ((opt = getopt_long(argc, argvopt, "s:",
+				  lgopts, &option_index)) != EOF) {
+
+		switch (opt) {
+		case 0:
+			if (strcmp(lgopts[option_index].name,
+					REQ_FILE_PATH_KEYWORD) == 0)
+				env.req_path = optarg;
+			else if (strcmp(lgopts[option_index].name,
+					RSP_FILE_PATH_KEYWORD) == 0)
+				env.rsp_path = optarg;
+			else if (strcmp(lgopts[option_index].name,
+					FOLDER_KEYWORD) == 0)
+				env.is_path_folder = 1;
+			else if (strcmp(lgopts[option_index].name,
+					CRYPTODEV_KEYWORD) == 0) {
+				ret = parse_cryptodev_arg(optarg);
+				if (ret < 0) {
+					cryptodev_fips_validate_usage(prgname);
+					return -EINVAL;
+				}
+			} else if (strcmp(lgopts[option_index].name,
+					CRYPTODEV_ID_KEYWORD) == 0) {
+				ret = parse_cryptodev_id_arg(optarg);
+				if (ret < 0) {
+					cryptodev_fips_validate_usage(prgname);
+					return -EINVAL;
+				}
+			} else {
+				cryptodev_fips_validate_usage(prgname);
+				return -EINVAL;
+			}
+			break;
+		default:
+			return -1;
+		}
+	}
+
+	if (env.req_path == NULL || env.rsp_path == NULL ||
+			env.dev_id == UINT32_MAX) {
+		cryptodev_fips_validate_usage(prgname);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+	int ret;
+
+	ret = rte_eal_init(argc, argv);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
+		return -1;
+	}
+
+	argc -= ret;
+	argv += ret;
+
+	ret = cryptodev_fips_validate_parse_args(argc, argv);
+	if (ret < 0)
+		rte_exit(EXIT_FAILURE, "Failed to parse arguments!\n");
+
+	ret = cryptodev_fips_validate_app_int();
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
+		return -1;
+	}
+
+	if (!env.is_path_folder) {
+		printf("Processing file %s... ", env.req_path);
+
+		ret = fips_test_init(env.req_path, env.rsp_path,
+			rte_cryptodev_name_get(env.dev_id));
+		if (ret < 0) {
+			RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
+					ret, env.req_path);
+			goto exit;
+		}
+
+
+		ret = fips_test_one_file();
+		if (ret < 0) {
+			RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
+					ret, env.req_path);
+			goto exit;
+		}
+
+		printf("Done\n");
+
+	} else {
+		struct dirent *dir;
+		DIR *d_req, *d_rsp;
+		char req_path[1024];
+		char rsp_path[1024];
+
+		d_req = opendir(env.req_path);
+		if (!d_req) {
+			RTE_LOG(ERR, USER1, "Error %i: Path %s not exist\n",
+					-EINVAL, env.req_path);
+			goto exit;
+		}
+
+		d_rsp = opendir(env.rsp_path);
+		if (!d_rsp) {
+			ret = mkdir(env.rsp_path, 0700);
+			if (ret == 0)
+				d_rsp = opendir(env.rsp_path);
+			else {
+				RTE_LOG(ERR, USER1, "Error %i: Invalid %s\n",
+						-EINVAL, env.rsp_path);
+				goto exit;
+			}
+		}
+		closedir(d_rsp);
+
+		while ((dir = readdir(d_req)) != NULL) {
+			if (strstr(dir->d_name, "req") == NULL)
+				continue;
+
+			snprintf(req_path, 1023, "%s/%s", env.req_path,
+					dir->d_name);
+			snprintf(rsp_path, 1023, "%s/%s", env.rsp_path,
+					dir->d_name);
+			strlcpy(strstr(rsp_path, "req"), "rsp", 4);
+
+			printf("Processing file %s... ", req_path);
+
+			ret = fips_test_init(req_path, rsp_path,
+			rte_cryptodev_name_get(env.dev_id));
+			if (ret < 0) {
+				RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
+						ret, req_path);
+				break;
+			}
+
+			ret = fips_test_one_file();
+			if (ret < 0) {
+				RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
+						ret, req_path);
+				break;
+			}
+
+			printf("Done\n");
+		}
+
+		closedir(d_req);
+	}
+
+
+exit:
+	fips_test_clear();
+	cryptodev_fips_validate_app_uninit();
+
+	return ret;
+
+}
+
+static void
+print_test_block(void)
+{
+	uint32_t i;
+
+	for (i = 0; i < info.nb_vec_lines; i++)
+		printf("%s\n", info.vec[i]);
+
+	printf("\n");
+}
+
+static int
+fips_test_one_file(void)
+{
+	int fetch_ret = 0, ret;
+
+	while (fetch_ret == 0) {
+		fetch_ret = fips_test_fetch_one_block();
+		if (fetch_ret < 0) {
+			RTE_LOG(ERR, USER1, "Error %i: Fetch block\n",
+					fetch_ret);
+			ret = fetch_ret;
+			goto error_one_case;
+		}
+
+		if (info.nb_vec_lines == 0) {
+			if (fetch_ret == -EOF)
+				break;
+
+			fprintf(info.fp_wr, "\n");
+			continue;
+		}
+
+		ret = fips_test_parse_one_case();
+		switch (ret) {
+		case 0:
+			if (ret == 0)
+				break;
+			RTE_LOG(ERR, USER1, "Error %i: test block\n",
+					ret);
+			goto error_one_case;
+		case 1:
+			break;
+		default:
+			RTE_LOG(ERR, USER1, "Error %i: Parse block\n",
+					ret);
+			goto error_one_case;
+		}
+
+		continue;
+error_one_case:
+		print_test_block();
+	}
+
+	fips_test_clear();
+
+}
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
new file mode 100644
index 0000000..cceed4f
--- /dev/null
+++ b/examples/fips_validation/meson.build
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Intel Corporation
+
+# meson file, for building this example as part of a main DPDK build.
+#
+# To build this example as a standalone application with an already-installed
+# DPDK instance, use 'make'
+
+deps += ['cryptodev']
+allow_experimental_apis = true
+sources = files(
+	'fips_validation.c',
+	'main.c'
+)
-- 
2.9.5

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

* [dpdk-dev] [PATCH v6 2/8] examples/fips_validation: support AES parsing
  2018-10-26 11:07   ` [dpdk-dev] [PATCH v6 " Marko Kovacevic
  2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 1/8] examples/fips_validation: add cryptodev fips compliant application Marko Kovacevic
@ 2018-10-26 11:07     ` Marko Kovacevic
  2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 3/8] examples/fips_validation: support HMAC parsing Marko Kovacevic
                       ` (7 subsequent siblings)
  9 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-26 11:07 UTC (permalink / raw)
  To: akhil.goyal; +Cc: dev, roy.fan.zhang, arkadiuszx.kusztal, Kovacevic, Marko

From: "Kovacevic, Marko" <marko.kovacevic@intel.com>

Added enablement for AES-CBC parser, to allow the
application to parser the aes request file and to validate all
test types supported.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 examples/fips_validation/Makefile              |   1 +
 examples/fips_validation/fips_validation.c     |   6 +
 examples/fips_validation/fips_validation.h     |  24 ++
 examples/fips_validation/fips_validation_aes.c | 186 +++++++++++++
 examples/fips_validation/main.c                | 346 ++++++++++++++++++++++++-
 examples/fips_validation/meson.build           |   1 +
 6 files changed, 563 insertions(+), 1 deletion(-)
 create mode 100644 examples/fips_validation/fips_validation_aes.c

diff --git a/examples/fips_validation/Makefile b/examples/fips_validation/Makefile
index 59d56c7..1eb1bc5 100644
--- a/examples/fips_validation/Makefile
+++ b/examples/fips_validation/Makefile
@@ -6,6 +6,7 @@ APP = fips_validation
 
 # all source are stored in SRCS-y
 SRCS-y := fips_validation.c
+SRCS-y += fips_validation_aes.c
 SRCS-y += main.c
 
 # Build using pkg-config variables if possible
diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index 8ed15f4..9e70a47 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -104,6 +104,12 @@ fips_test_parse_header(void)
 		return ret;
 
 	for (i = 0; i < info.nb_vec_lines; i++) {
+		if (strstr(info.vec[i], "AESVS")) {
+			info.algo = FIPS_TEST_ALGO_AES;
+			ret = parse_test_aes_init();
+			if (ret < 0)
+				return ret;
+		}
 
 		tmp = strstr(info.vec[i], "# Config info for ");
 		if (tmp != NULL) {
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index dd3bc09..e947de1 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -23,6 +23,7 @@
 #define FAX_FILE_PERFIX		"fax"
 
 enum fips_test_algorithms {
+		FIPS_TEST_ALGO_AES = 0,
 		FIPS_TEST_ALGO_MAX
 };
 
@@ -77,6 +78,21 @@ struct fips_test_callback {
 	struct fips_val *val;
 };
 
+enum fips_aesavs_test_types {
+	AESAVS_TYPE_GFXBOX = 1,
+	AESAVS_TYPE_KEYSBOX,
+	AESAVS_TYPE_VARKEY,
+	AESAVS_TYPE_VARTXT,
+	AESAVS_TYPE_MMT,
+	AESAVS_TYPE_MCT,
+};
+
+struct aesavs_interim_data {
+	enum fips_aesavs_test_types test_type;
+	uint32_t cipher_algo;
+	uint32_t key_len;
+};
+
 struct fips_test_interim_info {
 	FILE *fp_rd;
 	FILE *fp_wr;
@@ -87,6 +103,11 @@ struct fips_test_interim_info {
 	uint32_t nb_vec_lines;
 	char device_name[MAX_STRING_SIZE];
 
+	union {
+		struct aesavs_interim_data aes_data;
+
+	} interim_info;
+
 	enum fips_test_op op;
 
 	const struct fips_test_callback *callbacks;
@@ -117,6 +138,9 @@ void
 fips_test_write_one_case(void);
 
 int
+parse_test_aes_init(void);
+
+int
 parser_read_uint8_hex(uint8_t *value, const char *p);
 
 int
diff --git a/examples/fips_validation/fips_validation_aes.c b/examples/fips_validation/fips_validation_aes.c
new file mode 100644
index 0000000..f60b864
--- /dev/null
+++ b/examples/fips_validation/fips_validation_aes.c
@@ -0,0 +1,186 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+
+#include <rte_cryptodev.h>
+
+#include "fips_validation.h"
+
+#define MODE_STR	"AESVS"
+#define ALGO_STR	"test data for "
+#define OP_STR		"State"
+#define KEY_SIZE_STR	"Key Length : "
+
+
+#define COUNT_STR	"COUNT = "
+#define KEY_STR		"KEY = "
+#define IV_STR		"IV = "
+#define PT_STR		"PLAINTEXT = "
+#define CT_STR		"CIPHERTEXT = "
+
+#define OP_ENC_STR	"ENCRYPT"
+#define OP_DEC_STR	"DECRYPT"
+
+struct {
+	uint32_t type;
+	const char *desc;
+} aes_test_types[] = {
+		{AESAVS_TYPE_GFXBOX, "GFSbox"},
+		{AESAVS_TYPE_KEYSBOX, "KeySbox"},
+		{AESAVS_TYPE_VARKEY, "VarKey"},
+		{AESAVS_TYPE_VARTXT, "VarTxt"},
+		{AESAVS_TYPE_MMT, "MMT"},
+		{AESAVS_TYPE_MCT, "MCT"},
+};
+
+struct aes_test_algo {
+	const char *name;
+	enum rte_crypto_cipher_algorithm algo;
+} const algo_con[] = {
+		{"CBC", RTE_CRYPTO_CIPHER_AES_CBC},
+};
+
+static int
+parse_interim_enc_dec(const char *key,
+		__attribute__((__unused__)) char *text,
+		__attribute__((__unused__)) struct fips_val *val)
+{
+	if (strcmp(key, OP_ENC_STR) == 0)
+		info.op = FIPS_TEST_ENC_AUTH_GEN;
+	else if (strcmp(key, OP_DEC_STR) == 0)
+		info.op = FIPS_TEST_DEC_AUTH_VERIF;
+	else
+		return -1;
+
+	return 0;
+}
+
+struct fips_test_callback aes_tests_interim[] = {
+		{OP_ENC_STR, parse_interim_enc_dec, NULL},
+		{OP_DEC_STR, parse_interim_enc_dec, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback aes_tests_vectors[] = {
+		{KEY_STR, parse_uint8_hex_str, &vec.cipher_auth.key},
+		{IV_STR, parse_uint8_hex_str, &vec.iv},
+		{PT_STR, parse_uint8_hex_str, &vec.pt},
+		{CT_STR, parse_uint8_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback aes_tests_interim_vectors[] = {
+		{OP_ENC_STR, parse_interim_enc_dec, NULL},
+		{OP_DEC_STR, parse_interim_enc_dec, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback aes_writeback_callbacks[] = {
+		/** First element is used to pass COUNT string */
+		{COUNT_STR, NULL, NULL},
+		{IV_STR, writeback_hex_str, &vec.iv},
+		{KEY_STR, writeback_hex_str, &vec.cipher_auth.key},
+		{PT_STR, writeback_hex_str, &vec.pt},
+		{CT_STR, writeback_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+static int
+parse_test_aes_writeback(struct fips_val *val)
+{
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN)
+		fprintf(info.fp_wr, "%s", CT_STR);
+	else
+		fprintf(info.fp_wr, "%s", PT_STR);
+
+	parse_write_hex_str(val);
+
+	return 0;
+}
+
+static int
+rsp_test_aes_check(struct fips_val *val)
+{
+	struct fips_val *data;
+
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN)
+		data = &vec.ct;
+	else
+		data = &vec.pt;
+
+	if (memcmp(val->val, data->val, val->len) == 0)
+		fprintf(info.fp_wr, "Success\n");
+	else
+		fprintf(info.fp_wr, "Failed\n");
+
+	return 0;
+}
+
+int
+parse_test_aes_init(void)
+{
+	char *tmp;
+	uint32_t i, j;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		char *line = info.vec[i];
+
+		tmp = strstr(line, MODE_STR);
+		if (tmp) {
+			for (j = 0; j < RTE_DIM(aes_test_types); j++)
+				if (strstr(line, aes_test_types[j].desc)) {
+					info.interim_info.aes_data.test_type =
+							aes_test_types[j].type;
+					break;
+				}
+
+			if (j >= RTE_DIM(aes_test_types))
+				return -EINVAL;
+
+			tmp = strstr(line, ALGO_STR);
+			if (!tmp)
+				return -EINVAL;
+
+			tmp += strlen(ALGO_STR);
+			for (j = 0; j < RTE_DIM(algo_con); j++)
+				if (strcmp(algo_con[j].name, tmp) == 0) {
+					info.interim_info.aes_data.cipher_algo =
+						(uint32_t)algo_con[j].algo;
+					break;
+				}
+			if (j >= RTE_DIM(algo_con))
+				return -EINVAL;
+
+			continue;
+		}
+
+		tmp = strstr(line, OP_STR);
+		if (tmp)
+			continue;
+
+		tmp = strstr(line, KEY_SIZE_STR);
+		if (tmp) {
+			tmp += strlen(KEY_SIZE_STR);
+			if (parser_read_uint32
+					(&info.interim_info.aes_data.key_len,
+							tmp) < 0)
+				return -EINVAL;
+
+			info.interim_info.aes_data.key_len /= 8;
+
+			continue;
+		}
+	}
+
+	info.parse_writeback = parse_test_aes_writeback;
+	info.callbacks = aes_tests_vectors;
+	info.interim_callbacks = aes_tests_interim_vectors;
+	info.writeback_callbacks = aes_writeback_callbacks;
+	info.kat_check = rsp_test_aes_check;
+
+	return 0;
+}
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index 7083462..1f1ba99 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -329,6 +329,340 @@ 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;
+
+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);
+
+	__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;
+
+	memcpy(iv, vec.iv.val, 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);
+
+		if (!pt) {
+			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
+					-ENOMEM);
+			return -ENOMEM;
+		}
+
+		memcpy(pt, vec.pt.val, vec.pt.len);
+		sym->cipher.data.length = vec.pt.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;
+		}
+
+		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;
+		}
+
+		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);
+
+	return 0;
+}
+
+static int
+prepare_aes_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_cipher_xform *cipher_xform = &xform->cipher;
+
+	xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+
+	cipher_xform->algo = RTE_CRYPTO_CIPHER_AES_CBC;
+	cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_CIPHER_OP_ENCRYPT :
+			RTE_CRYPTO_CIPHER_OP_DECRYPT;
+	cipher_xform->key.data = vec.cipher_auth.key.val;
+	cipher_xform->key.length = vec.cipher_auth.key.len;
+	cipher_xform->iv.length = vec.iv.len;
+	cipher_xform->iv.offset = IV_OFF;
+
+	cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_AES_CBC;
+	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;
+	}
+
+	return 0;
+}
+
+static void
+get_writeback_data(struct fips_val *val)
+{
+	val->val = rte_pktmbuf_mtod(env.mbuf, uint8_t *);
+	val->len = rte_pktmbuf_pkt_len(env.mbuf);
+}
+
+static int
+fips_run_test(void)
+{
+	struct rte_crypto_sym_xform xform = {0};
+	uint16_t n_deqd;
+	int ret;
+
+	ret = test_ops.prepare_xform(&xform);
+	if (ret < 0)
+		return ret;
+
+	env.sess = rte_cryptodev_sym_session_create(env.mpool);
+	if (!env.sess)
+		return -ENOMEM;
+
+	ret = rte_cryptodev_sym_session_init(env.dev_id,
+			env.sess, &xform, env.mpool);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: Init session\n",
+				ret);
+		return ret;
+	}
+
+	ret = test_ops.prepare_op();
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
+				ret);
+		return ret;
+	}
+
+	if (rte_cryptodev_enqueue_burst(env.dev_id, 0, &env.op, 1) < 1) {
+		RTE_LOG(ERR, USER1, "Error: Failed enqueue\n");
+		return ret;
+	}
+
+	do {
+		struct rte_crypto_op *deqd_op;
+
+		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
+				1);
+	} while (n_deqd == 0);
+
+	vec.status = env.op->status;
+
+	rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
+	rte_cryptodev_sym_session_free(env.sess);
+	env.sess = NULL;
+
+	return ret;
+}
+
+static int
+fips_generic_test(void)
+{
+	struct fips_val val;
+	int ret;
+
+	fips_test_write_one_case();
+
+	ret = fips_run_test();
+	if (ret < 0) {
+		if (ret == -EPERM) {
+			fprintf(info.fp_wr, "Bypass\n\n");
+			return 0;
+		}
+
+		return ret;
+	}
+
+	get_writeback_data(&val);
+
+	switch (info.file_type) {
+	case FIPS_TYPE_REQ:
+	case FIPS_TYPE_RSP:
+		if (info.parse_writeback == NULL)
+			return -EPERM;
+		ret = info.parse_writeback(&val);
+		if (ret < 0)
+			return ret;
+		break;
+	case FIPS_TYPE_FAX:
+		if (info.kat_check == NULL)
+			return -EPERM;
+		ret = info.kat_check(&val);
+		if (ret < 0)
+			return ret;
+		break;
+	}
+
+	fprintf(info.fp_wr, "\n");
+
+	return 0;
+}
+
+static int
+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;
+	uint8_t prev_out[AES_BLOCK_SIZE] = {0};
+	uint8_t prev_in[AES_BLOCK_SIZE] = {0};
+	uint32_t i, j, k;
+	int ret;
+
+	for (i = 0; i < AES_EXTERN_ITER; i++) {
+		if (i != 0)
+			update_info_vec(i);
+
+		fips_test_write_one_case();
+
+		for (j = 0; j < AES_INTERN_ITER; j++) {
+			ret = fips_run_test();
+			if (ret < 0) {
+				if (ret == -EPERM) {
+					fprintf(info.fp_wr, "Bypass\n");
+					return 0;
+				}
+
+				return ret;
+			}
+
+			get_writeback_data(&val);
+
+			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
+				memcpy(prev_in, vec.ct.val, AES_BLOCK_SIZE);
+
+			if (j == 0) {
+				memcpy(prev_out, val.val, AES_BLOCK_SIZE);
+
+				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+					memcpy(vec.pt.val, vec.iv.val,
+							AES_BLOCK_SIZE);
+					memcpy(vec.iv.val, val.val,
+							AES_BLOCK_SIZE);
+				} else {
+					memcpy(vec.ct.val, vec.iv.val,
+							AES_BLOCK_SIZE);
+					memcpy(vec.iv.val, prev_in,
+							AES_BLOCK_SIZE);
+				}
+				continue;
+			}
+
+			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+				memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
+				memcpy(vec.pt.val, prev_out, AES_BLOCK_SIZE);
+			} else {
+				memcpy(vec.iv.val, prev_in, AES_BLOCK_SIZE);
+				memcpy(vec.ct.val, prev_out, AES_BLOCK_SIZE);
+			}
+
+			if (j == AES_INTERN_ITER - 1)
+				continue;
+
+			memcpy(prev_out, val.val, AES_BLOCK_SIZE);
+		}
+
+		info.parse_writeback(&val);
+		fprintf(info.fp_wr, "\n");
+
+		if (i == AES_EXTERN_ITER - 1)
+			continue;
+
+		/** update key */
+		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
+		for (k = 0; k < vec.cipher_auth.key.len; k++) {
+			switch (vec.cipher_auth.key.len) {
+			case 16:
+				val_key.val[k] ^= val.val[k];
+				break;
+			case 24:
+				if (k < 8)
+					val_key.val[k] ^= prev_out[k + 8];
+				else
+					val_key.val[k] ^= val.val[k - 8];
+				break;
+			case 32:
+				if (k < 16)
+					val_key.val[k] ^= prev_out[k];
+				else
+					val_key.val[k] ^= val.val[k - 16];
+				break;
+			default:
+				return -1;
+			}
+		}
+
+		if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
+			memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
+	}
+
+	return 0;
+}
+
+static int
+init_test_ops(void)
+{
+	switch (info.algo) {
+	case FIPS_TEST_ALGO_AES:
+		test_ops.prepare_op = prepare_cipher_op;
+		test_ops.prepare_xform  = prepare_aes_xform;
+		if (info.interim_info.aes_data.test_type == AESAVS_TYPE_MCT)
+			test_ops.test = fips_mct_aes_test;
+		else
+			test_ops.test = fips_generic_test;
+		break;
+
+	default:
+		return -1;
+	}
+
+	return 0;
+}
+
 static void
 print_test_block(void)
 {
@@ -345,7 +679,14 @@ fips_test_one_file(void)
 {
 	int fetch_ret = 0, ret;
 
-	while (fetch_ret == 0) {
+
+	ret = init_test_ops();
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: Init test op\n", ret);
+		return ret;
+	}
+
+	while (ret >= 0 && fetch_ret == 0) {
 		fetch_ret = fips_test_fetch_one_block();
 		if (fetch_ret < 0) {
 			RTE_LOG(ERR, USER1, "Error %i: Fetch block\n",
@@ -365,6 +706,7 @@ fips_test_one_file(void)
 		ret = fips_test_parse_one_case();
 		switch (ret) {
 		case 0:
+			ret = test_ops.test();
 			if (ret == 0)
 				break;
 			RTE_LOG(ERR, USER1, "Error %i: test block\n",
@@ -385,4 +727,6 @@ fips_test_one_file(void)
 
 	fips_test_clear();
 
+	return ret;
+
 }
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
index cceed4f..fb20541 100644
--- a/examples/fips_validation/meson.build
+++ b/examples/fips_validation/meson.build
@@ -9,6 +9,7 @@
 deps += ['cryptodev']
 allow_experimental_apis = true
 sources = files(
+	'fips_validation_aes.c',
 	'fips_validation.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v6 3/8] examples/fips_validation: support HMAC parsing
  2018-10-26 11:07   ` [dpdk-dev] [PATCH v6 " Marko Kovacevic
  2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 1/8] examples/fips_validation: add cryptodev fips compliant application Marko Kovacevic
  2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 2/8] examples/fips_validation: support AES parsing Marko Kovacevic
@ 2018-10-26 11:07     ` Marko Kovacevic
  2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 4/8] examples/fips_validation: support TDES parsing Marko Kovacevic
                       ` (6 subsequent siblings)
  9 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-26 11:07 UTC (permalink / raw)
  To: akhil.goyal; +Cc: dev, roy.fan.zhang, arkadiuszx.kusztal, Kovacevic, Marko

From: "Kovacevic, Marko" <marko.kovacevic@intel.com>

Added enablement for HMAC parser, to allow the
application to parser the hmac request files and to validate all
tests supported

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 examples/fips_validation/Makefile               |   1 +
 examples/fips_validation/fips_validation.c      |   5 ++
 examples/fips_validation/fips_validation.h      |   9 ++
 examples/fips_validation/fips_validation_hmac.c | 105 ++++++++++++++++++++++++
 examples/fips_validation/main.c                 | 103 +++++++++++++++++++++++
 examples/fips_validation/meson.build            |   1 +
 6 files changed, 224 insertions(+)
 create mode 100644 examples/fips_validation/fips_validation_hmac.c

diff --git a/examples/fips_validation/Makefile b/examples/fips_validation/Makefile
index 1eb1bc5..0d76101 100644
--- a/examples/fips_validation/Makefile
+++ b/examples/fips_validation/Makefile
@@ -7,6 +7,7 @@ APP = fips_validation
 # all source are stored in SRCS-y
 SRCS-y := fips_validation.c
 SRCS-y += fips_validation_aes.c
+SRCS-y += fips_validation_hmac.c
 SRCS-y += main.c
 
 # Build using pkg-config variables if possible
diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index 9e70a47..994bd0c 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -109,6 +109,11 @@ fips_test_parse_header(void)
 			ret = parse_test_aes_init();
 			if (ret < 0)
 				return ret;
+		} else if (strstr(info.vec[i], "HMAC")) {
+			info.algo = FIPS_TEST_ALGO_HMAC;
+			ret = parse_test_hmac_init();
+			if (ret < 0)
+				return ret;
 		}
 
 		tmp = strstr(info.vec[i], "# Config info for ");
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index e947de1..f9e3a3b 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -24,6 +24,7 @@
 
 enum fips_test_algorithms {
 		FIPS_TEST_ALGO_AES = 0,
+		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_MAX
 };
 
@@ -93,6 +94,10 @@ struct aesavs_interim_data {
 	uint32_t key_len;
 };
 
+struct hmac_interim_data {
+	enum rte_crypto_auth_algorithm algo;
+};
+
 struct fips_test_interim_info {
 	FILE *fp_rd;
 	FILE *fp_wr;
@@ -105,6 +110,7 @@ struct fips_test_interim_info {
 
 	union {
 		struct aesavs_interim_data aes_data;
+		struct hmac_interim_data hmac_data;
 
 	} interim_info;
 
@@ -141,6 +147,9 @@ int
 parse_test_aes_init(void);
 
 int
+parse_test_hmac_init(void);
+
+int
 parser_read_uint8_hex(uint8_t *value, const char *p);
 
 int
diff --git a/examples/fips_validation/fips_validation_hmac.c b/examples/fips_validation/fips_validation_hmac.c
new file mode 100644
index 0000000..97ac718
--- /dev/null
+++ b/examples/fips_validation/fips_validation_hmac.c
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+
+#include <rte_cryptodev.h>
+
+#include "fips_validation.h"
+
+#define ALGO_PREFIX	"[L="
+#define KEYLEN_STR	"Klen = "
+#define TAGLEN_STR	"Tlen = "
+
+#define COUNT_STR	"Count = "
+#define KEY_STR		"Key = "
+#define PT_STR		"Msg = "
+#define TAG_STR		"Mac = "
+
+struct hash_size_conversion {
+	const char *str;
+	enum rte_crypto_auth_algorithm algo;
+} hsc[] = {
+		{"20", RTE_CRYPTO_AUTH_SHA1_HMAC},
+		{"28", RTE_CRYPTO_AUTH_SHA224_HMAC},
+		{"32", RTE_CRYPTO_AUTH_SHA256_HMAC},
+		{"48", RTE_CRYPTO_AUTH_SHA384_HMAC},
+		{"64", RTE_CRYPTO_AUTH_SHA512_HMAC},
+};
+
+static int
+parse_interim_algo(__attribute__((__unused__)) const char *key,
+		char *text,
+		__attribute__((__unused__)) struct fips_val *val)
+{
+
+	uint32_t i;
+
+	for (i = 0; i < RTE_DIM(hsc); i++) {
+		if (strstr(text, hsc[i].str)) {
+			info.interim_info.hmac_data.algo = hsc[i].algo;
+			break;
+		}
+	}
+
+	if (i == RTE_DIM(hsc))
+		return -1;
+
+	return 0;
+}
+
+struct fips_test_callback hmac_tests_vectors[] = {
+		{KEYLEN_STR, parser_read_uint32_val, &vec.cipher_auth.key},
+		{TAGLEN_STR, parser_read_uint32_val, &vec.cipher_auth.digest},
+		{KEY_STR, parse_uint8_hex_str, &vec.cipher_auth.key},
+		{PT_STR, parse_uint8_hex_str, &vec.pt},
+		{TAG_STR, parse_uint8_hex_str, &vec.cipher_auth.digest},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback hmac_tests_interim_vectors[] = {
+		{ALGO_PREFIX, parse_interim_algo, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+static int
+parse_test_hmac_writeback(struct fips_val *val)
+{
+	struct fips_val val_local;
+
+	fprintf(info.fp_wr, "%s", TAG_STR);
+
+	val_local.val = val->val + vec.pt.len;
+	val_local.len = vec.cipher_auth.digest.len;
+
+	parse_write_hex_str(&val_local);
+	return 0;
+}
+
+static int
+rsp_test_hmac_check(struct fips_val *val)
+{
+	if (memcmp(val->val + vec.pt.len, vec.cipher_auth.digest.val,
+			vec.cipher_auth.digest.len) == 0)
+		fprintf(info.fp_wr, "Success\n");
+	else
+		fprintf(info.fp_wr, "Failed\n");
+
+	return 0;
+}
+
+int
+parse_test_hmac_init(void)
+{
+	info.op = FIPS_TEST_ENC_AUTH_GEN;
+	info.parse_writeback = parse_test_hmac_writeback;
+	info.callbacks = hmac_tests_vectors;
+	info.interim_callbacks = hmac_tests_interim_vectors;
+	info.writeback_callbacks = NULL;
+	info.kat_check = rsp_test_hmac_check;
+
+	return 0;
+}
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index 1f1ba99..da31d6a 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -401,6 +401,67 @@ prepare_cipher_op(void)
 }
 
 static int
+prepare_auth_op(void)
+{
+	struct rte_crypto_sym_op *sym = env.op->sym;
+
+	__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;
+
+	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.cipher_auth.digest.len);
+
+		if (!pt) {
+			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
+					-ENOMEM);
+			return -ENOMEM;
+		}
+
+		memcpy(pt, vec.pt.val, vec.pt.len);
+		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);
+
+	} 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 + vec.cipher_auth.digest.len);
+
+		if (!ct) {
+			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
+					-ENOMEM);
+			return -ENOMEM;
+		}
+
+		memcpy(ct, vec.ct.val, vec.ct.len);
+		sym->auth.data.length = vec.ct.len;
+		sym->auth.digest.data = vec.cipher_auth.digest.val;
+		sym->auth.digest.phys_addr = rte_malloc_virt2iova(
+				sym->auth.digest.data);
+	}
+
+	rte_crypto_op_attach_sym_session(env.op, env.sess);
+}
+
+static int
 prepare_aes_xform(struct rte_crypto_sym_xform *xform)
 {
 	const struct rte_cryptodev_symmetric_capability *cap;
@@ -440,6 +501,43 @@ prepare_aes_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_hmac_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 = info.interim_info.hmac_data.algo;
+	auth_xform->op = RTE_CRYPTO_AUTH_OP_GENERATE;
+	auth_xform->digest_length = vec.cipher_auth.digest.len;
+	auth_xform->key.data = vec.cipher_auth.key.val;
+	auth_xform->key.length = vec.cipher_auth.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 void
 get_writeback_data(struct fips_val *val)
 {
@@ -655,6 +753,11 @@ init_test_ops(void)
 		else
 			test_ops.test = fips_generic_test;
 		break;
+	case FIPS_TEST_ALGO_HMAC:
+		test_ops.prepare_op = prepare_auth_op;
+		test_ops.prepare_xform = prepare_hmac_xform;
+		test_ops.test = fips_generic_test;
+		break;
 
 	default:
 		return -1;
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
index fb20541..57bcf81 100644
--- a/examples/fips_validation/meson.build
+++ b/examples/fips_validation/meson.build
@@ -11,5 +11,6 @@ allow_experimental_apis = true
 sources = files(
 	'fips_validation_aes.c',
 	'fips_validation.c',
+	'fips_validation_hmac.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v6 4/8] examples/fips_validation: support TDES parsing
  2018-10-26 11:07   ` [dpdk-dev] [PATCH v6 " Marko Kovacevic
                       ` (2 preceding siblings ...)
  2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 3/8] examples/fips_validation: support HMAC parsing Marko Kovacevic
@ 2018-10-26 11:07     ` Marko Kovacevic
  2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 5/8] examples/fips_validation: support GCM parsing Marko Kovacevic
                       ` (5 subsequent siblings)
  9 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-26 11:07 UTC (permalink / raw)
  To: akhil.goyal; +Cc: dev, roy.fan.zhang, arkadiuszx.kusztal, Kovacevic, Marko

From: "Kovacevic, Marko" <marko.kovacevic@intel.com>

Added enablement for TDES parser, to allow the
application to parser the TDES request files and to validate all
test types supported.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 examples/fips_validation/Makefile               |   1 +
 examples/fips_validation/fips_validation.c      |   5 +
 examples/fips_validation/fips_validation.h      |  21 ++
 examples/fips_validation/fips_validation_aes.c  |   2 +
 examples/fips_validation/fips_validation_tdes.c | 264 ++++++++++++++++++++++++
 examples/fips_validation/main.c                 | 175 ++++++++++++++++
 examples/fips_validation/meson.build            |   1 +
 7 files changed, 469 insertions(+)
 create mode 100644 examples/fips_validation/fips_validation_tdes.c

diff --git a/examples/fips_validation/Makefile b/examples/fips_validation/Makefile
index 0d76101..57cc778 100644
--- a/examples/fips_validation/Makefile
+++ b/examples/fips_validation/Makefile
@@ -8,6 +8,7 @@ APP = fips_validation
 SRCS-y := fips_validation.c
 SRCS-y += fips_validation_aes.c
 SRCS-y += fips_validation_hmac.c
+SRCS-y += fips_validation_tdes.c
 SRCS-y += main.c
 
 # Build using pkg-config variables if possible
diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index 994bd0c..ce66b9b 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -114,6 +114,11 @@ fips_test_parse_header(void)
 			ret = parse_test_hmac_init();
 			if (ret < 0)
 				return ret;
+		} else if (strstr(info.vec[i], "TDES")) {
+			info.algo = FIPS_TEST_ALGO_TDES;
+			ret = parse_test_tdes_init();
+			if (ret < 0)
+				return 0;
 		}
 
 		tmp = strstr(info.vec[i], "# Config info for ");
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index f9e3a3b..69a2116 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -25,6 +25,7 @@
 enum fips_test_algorithms {
 		FIPS_TEST_ALGO_AES = 0,
 		FIPS_TEST_ALGO_HMAC,
+		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_MAX
 };
 
@@ -88,6 +89,17 @@ enum fips_aesavs_test_types {
 	AESAVS_TYPE_MCT,
 };
 
+enum fips_tdes_test_types {
+	TDES_INVERSE_PERMUTATION = 0,
+	TDES_PERMUTATION,
+	TDES_SUBSTITUTION_TABLE,
+	TDES_VARIABLE_KEY,
+	TDES_VARIABLE_TEXT,
+	TDES_KAT,
+	TDES_MCT, /* Monte Carlo (Modes) Test */
+	TDES_MMT /* Multi block Message Test */
+};
+
 struct aesavs_interim_data {
 	enum fips_aesavs_test_types test_type;
 	uint32_t cipher_algo;
@@ -98,6 +110,11 @@ struct hmac_interim_data {
 	enum rte_crypto_auth_algorithm algo;
 };
 
+struct tdes_interim_data {
+	enum fips_tdes_test_types test_type;
+	uint32_t nb_keys;
+};
+
 struct fips_test_interim_info {
 	FILE *fp_rd;
 	FILE *fp_wr;
@@ -111,6 +128,7 @@ struct fips_test_interim_info {
 	union {
 		struct aesavs_interim_data aes_data;
 		struct hmac_interim_data hmac_data;
+		struct tdes_interim_data tdes_data;
 
 	} interim_info;
 
@@ -147,6 +165,9 @@ int
 parse_test_aes_init(void);
 
 int
+parse_test_tdes_init(void);
+
+int
 parse_test_hmac_init(void);
 
 int
diff --git a/examples/fips_validation/fips_validation_aes.c b/examples/fips_validation/fips_validation_aes.c
index f60b864..8cbc158 100644
--- a/examples/fips_validation/fips_validation_aes.c
+++ b/examples/fips_validation/fips_validation_aes.c
@@ -33,6 +33,8 @@ struct {
 		{AESAVS_TYPE_KEYSBOX, "KeySbox"},
 		{AESAVS_TYPE_VARKEY, "VarKey"},
 		{AESAVS_TYPE_VARTXT, "VarTxt"},
+		{TDES_VARIABLE_TEXT, "VARIABLE PLAINTEXT/CIPHERTEXT"},
+		{TDES_VARIABLE_TEXT, "KAT"},
 		{AESAVS_TYPE_MMT, "MMT"},
 		{AESAVS_TYPE_MCT, "MCT"},
 };
diff --git a/examples/fips_validation/fips_validation_tdes.c b/examples/fips_validation/fips_validation_tdes.c
new file mode 100644
index 0000000..5064ff3
--- /dev/null
+++ b/examples/fips_validation/fips_validation_tdes.c
@@ -0,0 +1,264 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include <rte_malloc.h>
+#include <rte_cryptodev.h>
+
+#include "fips_validation.h"
+
+#define NEW_LINE_STR	"#"
+#define TEST_TYPE_KEY	" for CBC"
+#define TEST_CBCI_KEY	" for CBCI"
+
+#define ENC_STR		"[ENCRYPT]"
+#define DEC_STR		"[DECRYPT]"
+
+#define COUNT_STR	"COUNT = "
+#define KEY1_STR	"KEY1 = "
+#define KEY2_STR	"KEY2 = "
+#define KEY3_STR	"KEY3 = "
+
+#define KEYS_STR	"KEYs = "
+#define IV_STR		"IV = "
+#define PT_STR		"PLAINTEXT = "
+#define CT_STR		"CIPHERTEXT = "
+#define NK_STR		"NumKeys = "
+
+#define SET_STR		" = "
+
+#define PLAIN_TEXT	0
+#define CIPHER_TEXT	1
+#define KEY_TEXT	2
+#define IV_TEXT		3
+
+#define DEVICE_STR	"# Config Info for : "
+
+struct {
+	uint32_t type;
+	const char *desc;
+} test_types[] = {
+		{TDES_INVERSE_PERMUTATION, "INVERSE PERMUTATION"},
+		{TDES_PERMUTATION, "PERMUTATION OPERATION"},
+		{TDES_SUBSTITUTION_TABLE, "SUBSTITUTION TABLE"},
+		{TDES_VARIABLE_KEY, "VARIABLE KEY"},
+		{TDES_VARIABLE_TEXT, "VARIABLE PLAINTEXT/CIPHERTEXT"},
+		{TDES_VARIABLE_TEXT, "KAT"},
+		{TDES_MCT, "Monte Carlo (Modes) Test"},
+		{TDES_MMT, "Multi block Message Test"},
+};
+
+static int
+writeback_tdes_hex_str(const char *key, char *dst, struct fips_val *val);
+
+static int
+parse_tdes_uint8_hex_str(const char *key, char *src, struct fips_val *val);
+
+static int
+parse_tdes_interim(const char *key,
+		__attribute__((__unused__)) char *text,
+		struct fips_val *val);
+
+struct fips_test_callback tdes_tests_vectors[] = {
+		{KEYS_STR, parse_tdes_uint8_hex_str, &vec.cipher_auth.key},
+		{KEY1_STR, parse_tdes_uint8_hex_str, &vec.cipher_auth.key},
+		{KEY2_STR, parse_tdes_uint8_hex_str, &vec.cipher_auth.key},
+		{KEY3_STR, parse_tdes_uint8_hex_str, &vec.cipher_auth.key},
+		{IV_STR, parse_uint8_hex_str, &vec.iv},
+		{PT_STR, parse_uint8_hex_str, &vec.pt},
+		{CT_STR, parse_uint8_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback tdes_tests_interim_vectors[] = {
+		{ENC_STR, parse_tdes_interim, NULL},
+		{DEC_STR, parse_tdes_interim, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback tdes_writeback_callbacks[] = {
+		/** First element is used to pass COUNT string */
+		{COUNT_STR, NULL, NULL},
+		{IV_STR, writeback_hex_str, &vec.iv},
+		{KEY1_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
+		{KEY2_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
+		{KEY3_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
+		{KEYS_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
+		{PT_STR, writeback_hex_str, &vec.pt},
+		{CT_STR, writeback_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+static int
+parse_tdes_interim(const char *key,
+		__attribute__((__unused__)) char *text,
+		__attribute__((__unused__)) struct fips_val *val)
+{
+	if (strstr(key, ENC_STR))
+		info.op = FIPS_TEST_ENC_AUTH_GEN;
+	else if (strstr(key, DEC_STR))
+		info.op = FIPS_TEST_DEC_AUTH_VERIF;
+	else if (strstr(NK_STR, "NumKeys = 1"))
+		info.interim_info.tdes_data.nb_keys = 1;
+	else if (strstr(NK_STR, "NumKeys = 2"))
+		info.interim_info.tdes_data.nb_keys = 2;
+	else if (strstr(NK_STR, "NumKeys = 3"))
+		info.interim_info.tdes_data.nb_keys = 3;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int
+parse_tdes_uint8_hex_str(const char *key, char *src, struct fips_val *val)
+{
+	uint8_t tmp_key[24] = {0};
+	uint32_t len, i;
+
+	src += strlen(key);
+
+	len = strlen(src) / 2;
+
+	if (val->val) {
+		memcpy(tmp_key, val->val, val->len);
+		rte_free(val->val);
+	}
+
+	val->val = rte_zmalloc(NULL, 24, 0);
+	if (!val->val)
+		return -1;
+
+	memcpy(val->val, tmp_key, 24);
+
+	if (strstr(key, KEYS_STR)) {
+		for (i = 0; i < len; i++) {
+			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
+
+			if (parser_read_uint8_hex(&val->val[i], byte) < 0)
+				goto error_exit;
+		}
+
+		memcpy(val->val + 8, val->val, 8);
+		memcpy(val->val + 16, val->val, 8);
+
+	} else if (strstr(key, KEY1_STR)) {
+		for (i = 0; i < len; i++) {
+			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
+
+			if (parser_read_uint8_hex(&val->val[i], byte) < 0)
+				goto error_exit;
+		}
+
+		if (info.interim_info.tdes_data.nb_keys == 2)
+			memcpy(val->val + 16, val->val, 8);
+
+	} else if (strstr(key, KEY2_STR)) {
+		for (i = 0; i < len; i++) {
+			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
+
+			if (parser_read_uint8_hex(&val->val[i + 8], byte) < 0)
+				goto error_exit;
+		}
+
+	} else if (strstr(key, KEY3_STR)) {
+		for (i = 0; i < len; i++) {
+			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
+
+			if (parser_read_uint8_hex(&val->val[i + 16], byte) < 0)
+				goto error_exit;
+		}
+	} else
+		return -EINVAL;
+
+	val->len = 24;
+
+	return 0;
+
+error_exit:
+	rte_free(val->val);
+	memset(val, 0, sizeof(*val));
+	return -EINVAL;
+}
+
+static int
+parse_test_tdes_writeback(struct fips_val *val)
+{
+
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN)
+		fprintf(info.fp_wr, "%s", CT_STR);
+	else
+		fprintf(info.fp_wr, "%s", PT_STR);
+
+	parse_write_hex_str(val);
+
+	return 0;
+
+}
+
+static int
+writeback_tdes_hex_str(const char *key, char *dst, struct fips_val *val)
+{
+	struct fips_val tmp_val;
+
+	tmp_val.len = 8;
+
+	if (strstr(key, KEY1_STR))
+		tmp_val.val = val->val;
+	else if (strstr(key, KEY2_STR))
+		tmp_val.val = val->val + 8;
+	else if (strstr(key, KEY3_STR))
+		tmp_val.val = val->val + 16;
+
+	return writeback_hex_str(key, dst, &tmp_val);
+}
+
+static int
+rsp_test_tdes_check(struct fips_val *val)
+{
+	struct fips_val *data;
+
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN)
+		data = &vec.ct;
+	else
+		data = &vec.pt;
+
+	if (memcmp(val->val, data->val, val->len) == 0)
+		fprintf(info.fp_wr, "Success\n");
+	else
+		fprintf(info.fp_wr, "Failed\n");
+
+	return 0;
+}
+
+int
+parse_test_tdes_init(void)
+{
+	uint32_t i;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		char *line = info.vec[i];
+		uint32_t j;
+
+		if (strstr(line, TEST_CBCI_KEY))
+			return -EPERM;
+
+		for (j = 0; j < RTE_DIM(test_types); j++)
+			if (strstr(line, test_types[j].desc)) {
+				info.interim_info.tdes_data.test_type =
+						test_types[j].type;
+				break;
+			}
+	}
+
+	info.parse_writeback = parse_test_tdes_writeback;
+	info.callbacks = tdes_tests_vectors;
+	info.interim_callbacks = tdes_tests_interim_vectors;
+	info.writeback_callbacks = tdes_writeback_callbacks;
+	info.kat_check = rsp_test_tdes_check;
+
+	return 0;
+}
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index da31d6a..3880681 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -502,6 +502,46 @@ prepare_aes_xform(struct rte_crypto_sym_xform *xform)
 }
 
 static int
+prepare_tdes_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_cipher_xform *cipher_xform = &xform->cipher;
+
+	xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+
+	cipher_xform->algo = RTE_CRYPTO_CIPHER_3DES_CBC;
+	cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_CIPHER_OP_ENCRYPT :
+			RTE_CRYPTO_CIPHER_OP_DECRYPT;
+	cipher_xform->key.data = vec.cipher_auth.key.val;
+	cipher_xform->key.length = vec.cipher_auth.key.len;
+	cipher_xform->iv.length = vec.iv.len;
+	cipher_xform->iv.offset = IV_OFF;
+
+	cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_3DES_CBC;
+	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;
+	}
+
+	return 0;
+}
+
+static int
 prepare_hmac_xform(struct rte_crypto_sym_xform *xform)
 {
 	const struct rte_cryptodev_symmetric_capability *cap;
@@ -640,6 +680,133 @@ fips_generic_test(void)
 }
 
 static int
+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;
+	uint8_t prev_out[TDES_BLOCK_SIZE];
+	uint8_t prev_prev_out[TDES_BLOCK_SIZE];
+	uint8_t prev_in[TDES_BLOCK_SIZE];
+	uint32_t i, j, k;
+	int ret;
+
+	for (i = 0; i < TDES_EXTERN_ITER; i++) {
+		if (i != 0)
+			update_info_vec(i);
+
+		fips_test_write_one_case();
+
+		for (j = 0; j < TDES_INTERN_ITER; j++) {
+			ret = fips_run_test();
+			if (ret < 0) {
+				if (ret == -EPERM) {
+					fprintf(info.fp_wr, "Bypass\n");
+					return 0;
+				}
+
+				return ret;
+			}
+
+			get_writeback_data(&val);
+
+			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
+				memcpy(prev_in, vec.ct.val, TDES_BLOCK_SIZE);
+
+			if (j == 0) {
+				memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
+
+				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+					memcpy(vec.pt.val, vec.iv.val,
+							TDES_BLOCK_SIZE);
+					memcpy(vec.iv.val, val.val,
+							TDES_BLOCK_SIZE);
+				} else {
+					memcpy(vec.iv.val, vec.ct.val,
+							TDES_BLOCK_SIZE);
+					memcpy(vec.ct.val, val.val,
+							TDES_BLOCK_SIZE);
+				}
+				continue;
+			}
+
+			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+				memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
+				memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
+			} else {
+				memcpy(vec.iv.val, vec.ct.val, TDES_BLOCK_SIZE);
+				memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
+			}
+
+			if (j == TDES_INTERN_ITER - 1)
+				continue;
+
+			memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
+
+			if (j == TDES_INTERN_ITER - 3)
+				memcpy(prev_prev_out, val.val, TDES_BLOCK_SIZE);
+		}
+
+		info.parse_writeback(&val);
+		fprintf(info.fp_wr, "\n");
+
+		if (i == TDES_EXTERN_ITER - 1)
+			continue;
+
+		/** update key */
+		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
+
+		if (info.interim_info.tdes_data.nb_keys == 0) {
+			if (memcmp(val_key.val, val_key.val + 8, 8) == 0)
+				info.interim_info.tdes_data.nb_keys = 1;
+			else if (memcmp(val_key.val, val_key.val + 16, 8) == 0)
+				info.interim_info.tdes_data.nb_keys = 2;
+			else
+				info.interim_info.tdes_data.nb_keys = 3;
+
+		}
+
+		for (k = 0; k < TDES_BLOCK_SIZE; k++) {
+
+			switch (info.interim_info.tdes_data.nb_keys) {
+			case 3:
+				val_key.val[k] ^= val.val[k];
+				val_key.val[k + 8] ^= prev_out[k];
+				val_key.val[k + 16] ^= prev_prev_out[k];
+				break;
+			case 2:
+				val_key.val[k] ^= val.val[k];
+				val_key.val[k + 8] ^= prev_out[k];
+				val_key.val[k + 16] ^= val.val[k];
+				break;
+			default: /* case 1 */
+				val_key.val[k] ^= val.val[k];
+				val_key.val[k + 8] ^= val.val[k];
+				val_key.val[k + 16] ^= val.val[k];
+				break;
+			}
+
+		}
+
+		for (k = 0; k < 24; k++)
+			val_key.val[k] = (__builtin_popcount(val_key.val[k]) &
+					0x1) ?
+					val_key.val[k] : (val_key.val[k] ^ 0x1);
+
+		if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+			memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
+			memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
+		} else {
+			memcpy(vec.iv.val, prev_out, TDES_BLOCK_SIZE);
+			memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
+		}
+	}
+
+	return 0;
+}
+
+static int
 fips_mct_aes_test(void)
 {
 #define AES_BLOCK_SIZE	16
@@ -758,6 +925,14 @@ init_test_ops(void)
 		test_ops.prepare_xform = prepare_hmac_xform;
 		test_ops.test = fips_generic_test;
 		break;
+	case FIPS_TEST_ALGO_TDES:
+		test_ops.prepare_op = prepare_cipher_op;
+		test_ops.prepare_xform  = prepare_tdes_xform;
+		if (info.interim_info.tdes_data.test_type == TDES_MCT)
+			test_ops.test = fips_mct_tdes_test;
+		else
+			test_ops.test = fips_generic_test;
+		break;
 
 	default:
 		return -1;
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
index 57bcf81..781ad5f 100644
--- a/examples/fips_validation/meson.build
+++ b/examples/fips_validation/meson.build
@@ -12,5 +12,6 @@ sources = files(
 	'fips_validation_aes.c',
 	'fips_validation.c',
 	'fips_validation_hmac.c',
+	'fips_validation_tdes.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v6 5/8] examples/fips_validation: support GCM parsing
  2018-10-26 11:07   ` [dpdk-dev] [PATCH v6 " Marko Kovacevic
                       ` (3 preceding siblings ...)
  2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 4/8] examples/fips_validation: support TDES parsing Marko Kovacevic
@ 2018-10-26 11:07     ` Marko Kovacevic
  2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 6/8] examples/fips_validation: support CMAC parsing Marko Kovacevic
                       ` (4 subsequent siblings)
  9 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-26 11:07 UTC (permalink / raw)
  To: akhil.goyal; +Cc: dev, roy.fan.zhang, arkadiuszx.kusztal, Kovacevic, Marko

From: "Kovacevic, Marko" <marko.kovacevic@intel.com>

Added enablement for GCM parser, to allow the
application to parser the GCM request file and to validate all
tests supported.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 examples/fips_validation/Makefile              |   1 +
 examples/fips_validation/fips_validation.c     |   5 +
 examples/fips_validation/fips_validation.h     |   4 +
 examples/fips_validation/fips_validation_gcm.c | 125 +++++++++++++++++++++++++
 examples/fips_validation/main.c                | 116 ++++++++++++++++++++++-
 examples/fips_validation/meson.build           |   1 +
 6 files changed, 251 insertions(+), 1 deletion(-)
 create mode 100644 examples/fips_validation/fips_validation_gcm.c

diff --git a/examples/fips_validation/Makefile b/examples/fips_validation/Makefile
index 57cc778..6373ac3 100644
--- a/examples/fips_validation/Makefile
+++ b/examples/fips_validation/Makefile
@@ -9,6 +9,7 @@ SRCS-y := fips_validation.c
 SRCS-y += fips_validation_aes.c
 SRCS-y += fips_validation_hmac.c
 SRCS-y += fips_validation_tdes.c
+SRCS-y += fips_validation_gcm.c
 SRCS-y += main.c
 
 # Build using pkg-config variables if possible
diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index ce66b9b..9a6005a 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -109,6 +109,11 @@ fips_test_parse_header(void)
 			ret = parse_test_aes_init();
 			if (ret < 0)
 				return ret;
+		} else if (strstr(info.vec[i], "GCM")) {
+			info.algo = FIPS_TEST_ALGO_AES_GCM;
+			ret = parse_test_gcm_init();
+			if (ret < 0)
+				return ret;
 		} else if (strstr(info.vec[i], "HMAC")) {
 			info.algo = FIPS_TEST_ALGO_HMAC;
 			ret = parse_test_hmac_init();
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index 69a2116..4cceff5 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -24,6 +24,7 @@
 
 enum fips_test_algorithms {
 		FIPS_TEST_ALGO_AES = 0,
+		FIPS_TEST_ALGO_AES_GCM,
 		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_MAX
@@ -171,6 +172,9 @@ int
 parse_test_hmac_init(void);
 
 int
+parse_test_gcm_init(void);
+
+int
 parser_read_uint8_hex(uint8_t *value, const char *p);
 
 int
diff --git a/examples/fips_validation/fips_validation_gcm.c b/examples/fips_validation/fips_validation_gcm.c
new file mode 100644
index 0000000..0509b10
--- /dev/null
+++ b/examples/fips_validation/fips_validation_gcm.c
@@ -0,0 +1,125 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+
+#include <rte_cryptodev.h>
+
+#include "fips_validation.h"
+
+#define NEW_LINE_STR	"#"
+#define OP_STR		"GCM "
+
+#define PARAM_PREFIX	"["
+#define KEYLEN_STR	"Keylen = "
+#define IVLEN_STR	"IVlen = "
+#define PTLEN_STR	"PTlen = "
+#define AADLEN_STR	"AADlen = "
+#define TAGLEN_STR	"Taglen = "
+
+#define COUNT_STR	"Count = "
+#define KEY_STR		"Key = "
+#define IV_STR		"IV = "
+#define PT_STR		"PT = "
+#define CT_STR		"CT = "
+#define TAG_STR		"Tag = "
+#define AAD_STR		"AAD = "
+
+#define OP_ENC_STR	"Encrypt"
+#define OP_DEC_STR	"Decrypt"
+
+#define NEG_TEST_STR	"FAIL"
+
+struct fips_test_callback gcm_dec_vectors[] = {
+		{KEY_STR, parse_uint8_known_len_hex_str, &vec.cipher_auth.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.cipher_auth.aad},
+		{TAG_STR, parse_uint8_known_len_hex_str,
+				&vec.cipher_auth.digest},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+struct fips_test_callback gcm_interim_vectors[] = {
+		{KEYLEN_STR, parser_read_uint32_bit_val, &vec.cipher_auth.key},
+		{IVLEN_STR, parser_read_uint32_bit_val, &vec.iv},
+		{PTLEN_STR, parser_read_uint32_bit_val, &vec.pt},
+		{AADLEN_STR, parser_read_uint32_bit_val, &vec.cipher_auth.aad},
+		{TAGLEN_STR, parser_read_uint32_bit_val,
+				&vec.cipher_auth.digest},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback gcm_enc_vectors[] = {
+		{KEY_STR, parse_uint8_known_len_hex_str, &vec.cipher_auth.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.cipher_auth.aad},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+static int
+parse_test_gcm_writeback(struct fips_val *val)
+{
+	struct fips_val tmp_val;
+
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+		fprintf(info.fp_wr, "%s", CT_STR);
+
+		tmp_val.val = val->val;
+		tmp_val.len = vec.pt.len;
+
+		parse_write_hex_str(&tmp_val);
+
+		fprintf(info.fp_wr, "%s", TAG_STR);
+
+		tmp_val.val = val->val + vec.pt.len;
+		tmp_val.len = val->len - vec.pt.len;
+
+		parse_write_hex_str(&tmp_val);
+	} else {
+		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS) {
+			fprintf(info.fp_wr, "%s", PT_STR);
+
+			tmp_val.val = val->val;
+			tmp_val.len = vec.pt.len;
+
+			parse_write_hex_str(&tmp_val);
+		} else
+			fprintf(info.fp_wr, "%s\n", NEG_TEST_STR);
+	}
+
+	return 0;
+}
+
+int
+parse_test_gcm_init(void)
+{
+	char *tmp;
+	uint32_t i;
+
+
+	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;
+			} else if (strstr(line, OP_DEC_STR)) {
+				info.op = FIPS_TEST_DEC_AUTH_VERIF;
+				info.callbacks = gcm_dec_vectors;
+			} else
+				return -EINVAL;
+		}
+	}
+
+	info.interim_callbacks = gcm_interim_vectors;
+	info.parse_writeback = parse_test_gcm_writeback;
+
+	return 0;
+}
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index 3880681..c693e87 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -462,6 +462,70 @@ prepare_auth_op(void)
 }
 
 static int
+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);
+
+	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+	rte_pktmbuf_reset(env.mbuf);
+
+	memcpy(iv, vec.iv.val, vec.iv.len);
+
+	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 (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);
+
+		if (!pt) {
+			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
+					-ENOMEM);
+			return -ENOMEM;
+		}
+
+		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);
+	} 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;
+		}
+
+		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);
+	}
+
+	rte_crypto_op_attach_sym_session(env.op, env.sess);
+}
+
+static int
 prepare_aes_xform(struct rte_crypto_sym_xform *xform)
 {
 	const struct rte_cryptodev_symmetric_capability *cap;
@@ -578,6 +642,52 @@ prepare_hmac_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_gcm_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_aead_xform *aead_xform = &xform->aead;
+
+	xform->type = RTE_CRYPTO_SYM_XFORM_AEAD;
+
+	aead_xform->algo = RTE_CRYPTO_AEAD_AES_GCM;
+	aead_xform->aad_length = vec.aead.aad.len;
+	aead_xform->digest_length = vec.aead.digest.len;
+	aead_xform->iv.offset = IV_OFF;
+	aead_xform->iv.length = vec.iv.len;
+	aead_xform->key.data = vec.aead.key.val;
+	aead_xform->key.length = vec.aead.key.len;
+	aead_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_AEAD_OP_ENCRYPT :
+			RTE_CRYPTO_AEAD_OP_DECRYPT;
+
+	cap_idx.algo.aead = aead_xform->algo;
+	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
+
+	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_aead(cap,
+			aead_xform->key.length,
+			aead_xform->digest_length, aead_xform->aad_length,
+			aead_xform->iv.length) != 0) {
+		RTE_LOG(ERR, USER1,
+			"PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n",
+				info.device_name, aead_xform->key.length,
+				aead_xform->digest_length,
+				aead_xform->aad_length,
+				aead_xform->iv.length);
+		return -EPERM;
+	}
+
+	return 0;
+}
+
 static void
 get_writeback_data(struct fips_val *val)
 {
@@ -933,7 +1043,11 @@ init_test_ops(void)
 		else
 			test_ops.test = fips_generic_test;
 		break;
-
+	case FIPS_TEST_ALGO_AES_GCM:
+		test_ops.prepare_op = prepare_aead_op;
+		test_ops.prepare_xform = prepare_gcm_xform;
+		test_ops.test = fips_generic_test;
+		break;
 	default:
 		return -1;
 	}
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
index 781ad5f..0cc8bc4 100644
--- a/examples/fips_validation/meson.build
+++ b/examples/fips_validation/meson.build
@@ -13,5 +13,6 @@ sources = files(
 	'fips_validation.c',
 	'fips_validation_hmac.c',
 	'fips_validation_tdes.c',
+	'fips_validation_gcm.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v6 6/8] examples/fips_validation: support CMAC parsing
  2018-10-26 11:07   ` [dpdk-dev] [PATCH v6 " Marko Kovacevic
                       ` (4 preceding siblings ...)
  2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 5/8] examples/fips_validation: support GCM parsing Marko Kovacevic
@ 2018-10-26 11:07     ` Marko Kovacevic
  2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 7/8] examples/fips_validation: support CCM parsing Marko Kovacevic
                       ` (3 subsequent siblings)
  9 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-26 11:07 UTC (permalink / raw)
  To: akhil.goyal; +Cc: dev, roy.fan.zhang, arkadiuszx.kusztal, Kovacevic, Marko

From: "Kovacevic, Marko" <marko.kovacevic@intel.com>

Added enablement for CMAC parser, to allow the
application to parser the cmac request files and to validate all
test types supported.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 examples/fips_validation/Makefile               |   1 +
 examples/fips_validation/fips_validation.c      |   5 +
 examples/fips_validation/fips_validation.h      |   4 +
 examples/fips_validation/fips_validation_cmac.c | 116 ++++++++++++++++++++++++
 examples/fips_validation/main.c                 |  43 +++++++++
 examples/fips_validation/meson.build            |   1 +
 6 files changed, 170 insertions(+)
 create mode 100644 examples/fips_validation/fips_validation_cmac.c

diff --git a/examples/fips_validation/Makefile b/examples/fips_validation/Makefile
index 6373ac3..77b15ae 100644
--- a/examples/fips_validation/Makefile
+++ b/examples/fips_validation/Makefile
@@ -10,6 +10,7 @@ SRCS-y += fips_validation_aes.c
 SRCS-y += fips_validation_hmac.c
 SRCS-y += fips_validation_tdes.c
 SRCS-y += fips_validation_gcm.c
+SRCS-y += fips_validation_cmac.c
 SRCS-y += main.c
 
 # Build using pkg-config variables if possible
diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index 9a6005a..3b8f1ae 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -114,6 +114,11 @@ fips_test_parse_header(void)
 			ret = parse_test_gcm_init();
 			if (ret < 0)
 				return ret;
+		} else if (strstr(info.vec[i], "CMAC")) {
+			info.algo = FIPS_TEST_ALGO_AES_CMAC;
+			ret = parse_test_cmac_init();
+			if (ret < 0)
+				return 0;
 		} else if (strstr(info.vec[i], "HMAC")) {
 			info.algo = FIPS_TEST_ALGO_HMAC;
 			ret = parse_test_hmac_init();
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index 4cceff5..8dffe8e 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -25,6 +25,7 @@
 enum fips_test_algorithms {
 		FIPS_TEST_ALGO_AES = 0,
 		FIPS_TEST_ALGO_AES_GCM,
+		FIPS_TEST_ALGO_AES_CMAC,
 		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_MAX
@@ -175,6 +176,9 @@ int
 parse_test_gcm_init(void);
 
 int
+parse_test_cmac_init(void);
+
+int
 parser_read_uint8_hex(uint8_t *value, const char *p);
 
 int
diff --git a/examples/fips_validation/fips_validation_cmac.c b/examples/fips_validation/fips_validation_cmac.c
new file mode 100644
index 0000000..54c951e
--- /dev/null
+++ b/examples/fips_validation/fips_validation_cmac.c
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+#include <rte_string_fns.h>
+
+#include <rte_cryptodev.h>
+
+#include "fips_validation.h"
+
+#define NEW_LINE_STR	"#"
+#define OP_STR		"CMAC"
+
+#define ALGO_STR	"Alg = "
+#define MODE_STR	"Mode = "
+
+#define COUNT_STR	"Count = "
+#define KLEN_STR	"Klen = "
+#define PTLEN_STR	"Mlen = "
+#define TAGLEN_STR	"Tlen = "
+#define KEY_STR		"Key = "
+#define PT_STR		"Msg = "
+#define TAG_STR		"Mac = "
+
+#define GEN_STR		"Generate"
+#define VERIF_STR	"Verify"
+
+#define POS_NEG_STR	"Result = "
+#define PASS_STR	"P"
+#define FAIL_STR	"F"
+
+struct hash_algo_conversion {
+	const char *str;
+	enum fips_test_algorithms algo;
+} cmac_algo[] = {
+		{"AES", FIPS_TEST_ALGO_AES_CMAC},
+};
+
+static int
+parse_test_cmac_writeback(struct fips_val *val)
+{
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+		struct fips_val tmp_val = {val->val + vec.pt.len,
+				vec.cipher_auth.digest.len};
+
+		fprintf(info.fp_wr, "%s", TAG_STR);
+		parse_write_hex_str(&tmp_val);
+	} else {
+		fprintf(info.fp_wr, "%s", POS_NEG_STR);
+
+		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS)
+			fprintf(info.fp_wr, "%s\n", PASS_STR);
+		else if (vec.status == RTE_CRYPTO_OP_STATUS_AUTH_FAILED)
+			fprintf(info.fp_wr, "%s\n", FAIL_STR);
+		else
+			fprintf(info.fp_wr, "Error\n");
+	}
+
+	return 0;
+}
+
+struct fips_test_callback cmac_tests_vectors[] = {
+		{KLEN_STR, parser_read_uint32_val, &vec.cipher_auth.key},
+		{PTLEN_STR, parser_read_uint32_val, &vec.pt},
+		{TAGLEN_STR, parser_read_uint32_val, &vec.cipher_auth.digest},
+		{KEY_STR, parse_uint8_hex_str, &vec.cipher_auth.key},
+		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
+		{TAG_STR, parse_uint8_known_len_hex_str,
+				&vec.cipher_auth.digest},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+int
+parse_test_cmac_init(void)
+{
+	char *tmp;
+	uint32_t i, j;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		char *line = info.vec[i];
+
+		tmp = strstr(line, ALGO_STR);
+		if (!tmp)
+			continue;
+
+		for (j = 0; j < RTE_DIM(cmac_algo); j++) {
+			if (!strstr(line, cmac_algo[j].str))
+				continue;
+
+			info.algo = cmac_algo[j].algo;
+			break;
+		}
+
+		if (j == RTE_DIM(cmac_algo))
+			return -EINVAL;
+
+		tmp = strstr(line, MODE_STR);
+		if (!tmp)
+			return -1;
+
+		if (strstr(tmp, GEN_STR))
+			info.op = FIPS_TEST_ENC_AUTH_GEN;
+		else if (strstr(tmp, VERIF_STR))
+			info.op = FIPS_TEST_DEC_AUTH_VERIF;
+		else
+			return -EINVAL;
+	}
+
+	info.parse_writeback = parse_test_cmac_writeback;
+	info.callbacks = cmac_tests_vectors;
+
+	return 0;
+}
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index c693e87..e953f3e 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -688,6 +688,44 @@ prepare_gcm_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_cmac_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_CMAC;
+	auth_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_AUTH_OP_GENERATE : RTE_CRYPTO_AUTH_OP_VERIFY;
+	auth_xform->digest_length = vec.cipher_auth.digest.len;
+	auth_xform->key.data = vec.cipher_auth.key.val;
+	auth_xform->key.length = vec.cipher_auth.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 void
 get_writeback_data(struct fips_val *val)
 {
@@ -1048,6 +1086,11 @@ init_test_ops(void)
 		test_ops.prepare_xform = prepare_gcm_xform;
 		test_ops.test = fips_generic_test;
 		break;
+	case FIPS_TEST_ALGO_AES_CMAC:
+		test_ops.prepare_op = prepare_auth_op;
+		test_ops.prepare_xform = prepare_cmac_xform;
+		test_ops.test = fips_generic_test;
+		break;
 	default:
 		return -1;
 	}
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
index 0cc8bc4..a0d38fa 100644
--- a/examples/fips_validation/meson.build
+++ b/examples/fips_validation/meson.build
@@ -14,5 +14,6 @@ sources = files(
 	'fips_validation_hmac.c',
 	'fips_validation_tdes.c',
 	'fips_validation_gcm.c',
+	'fips_validation_cmac.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v6 7/8] examples/fips_validation: support CCM parsing
  2018-10-26 11:07   ` [dpdk-dev] [PATCH v6 " Marko Kovacevic
                       ` (5 preceding siblings ...)
  2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 6/8] examples/fips_validation: support CMAC parsing Marko Kovacevic
@ 2018-10-26 11:07     ` Marko Kovacevic
  2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 8/8] doc: add fips validation application guide Marko Kovacevic
                       ` (2 subsequent siblings)
  9 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-26 11:07 UTC (permalink / raw)
  To: akhil.goyal; +Cc: dev, roy.fan.zhang, arkadiuszx.kusztal, Kovacevic, Marko

From: "Kovacevic, Marko" <marko.kovacevic@intel.com>

Added enablement for CCM parser, to allow the
application to parser the ccm request files and to validate all
test types supported.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 examples/fips_validation/Makefile              |   1 +
 examples/fips_validation/fips_validation.c     |   5 +
 examples/fips_validation/fips_validation.h     |  22 ++
 examples/fips_validation/fips_validation_ccm.c | 272 +++++++++++++++++++++++++
 examples/fips_validation/main.c                |  56 ++++-
 examples/fips_validation/meson.build           |   1 +
 6 files changed, 356 insertions(+), 1 deletion(-)
 create mode 100644 examples/fips_validation/fips_validation_ccm.c

diff --git a/examples/fips_validation/Makefile b/examples/fips_validation/Makefile
index 77b15ae..7b1fe34 100644
--- a/examples/fips_validation/Makefile
+++ b/examples/fips_validation/Makefile
@@ -11,6 +11,7 @@ SRCS-y += fips_validation_hmac.c
 SRCS-y += fips_validation_tdes.c
 SRCS-y += fips_validation_gcm.c
 SRCS-y += fips_validation_cmac.c
+SRCS-y += fips_validation_ccm.c
 SRCS-y += main.c
 
 # Build using pkg-config variables if possible
diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index 3b8f1ae..d5a16b3 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -119,6 +119,11 @@ fips_test_parse_header(void)
 			ret = parse_test_cmac_init();
 			if (ret < 0)
 				return 0;
+		} else if (strstr(info.vec[i], "CCM")) {
+			info.algo = FIPS_TEST_ALGO_AES_CCM;
+			ret = parse_test_ccm_init();
+			if (ret < 0)
+				return 0;
 		} else if (strstr(info.vec[i], "HMAC")) {
 			info.algo = FIPS_TEST_ALGO_HMAC;
 			ret = parse_test_hmac_init();
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index 8dffe8e..3e291bc 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -26,6 +26,7 @@ enum fips_test_algorithms {
 		FIPS_TEST_ALGO_AES = 0,
 		FIPS_TEST_ALGO_AES_GCM,
 		FIPS_TEST_ALGO_AES_CMAC,
+		FIPS_TEST_ALGO_AES_CCM,
 		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_MAX
@@ -102,6 +103,14 @@ enum fips_tdes_test_types {
 	TDES_MMT /* Multi block Message Test */
 };
 
+enum fips_ccm_test_types {
+	CCM_VADT	= 1, /* Variable Associated Data Test */
+	CCM_VPT,		 /* Variable Payload Test */
+	CCM_VNT,		 /* Variable Nonce Test */
+	CCM_VTT,		 /* Variable Tag Test */
+	CCM_DVPT,	 /*  Decryption-Verification Process Test */
+};
+
 struct aesavs_interim_data {
 	enum fips_aesavs_test_types test_type;
 	uint32_t cipher_algo;
@@ -117,6 +126,15 @@ struct tdes_interim_data {
 	uint32_t nb_keys;
 };
 
+struct ccm_interim_data {
+	enum fips_ccm_test_types test_type;
+	uint32_t aad_len;
+	uint32_t pt_len;
+	uint32_t digest_len;
+	uint32_t key_len;
+	uint32_t iv_len;
+};
+
 struct fips_test_interim_info {
 	FILE *fp_rd;
 	FILE *fp_wr;
@@ -131,6 +149,7 @@ struct fips_test_interim_info {
 		struct aesavs_interim_data aes_data;
 		struct hmac_interim_data hmac_data;
 		struct tdes_interim_data tdes_data;
+		struct ccm_interim_data ccm_data;
 
 	} interim_info;
 
@@ -179,6 +198,9 @@ int
 parse_test_cmac_init(void);
 
 int
+parse_test_ccm_init(void);
+
+int
 parser_read_uint8_hex(uint8_t *value, const char *p);
 
 int
diff --git a/examples/fips_validation/fips_validation_ccm.c b/examples/fips_validation/fips_validation_ccm.c
new file mode 100644
index 0000000..632999c
--- /dev/null
+++ b/examples/fips_validation/fips_validation_ccm.c
@@ -0,0 +1,272 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <rte_string_fns.h>
+#include <rte_cryptodev.h>
+#include <rte_malloc.h>
+
+#include "fips_validation.h"
+
+#define DVPT_STR	"CCM-DVPT"
+#define VADT_STR	"CCM-VADT"
+#define VPT_STR		"CCM-VPT"
+#define VNT_STR		"CCM-VNT"
+#define VTT_STR		"CCM-VTT"
+
+#define PARAM_PREFIX	"["
+#define ALEN_PREFIX	"Alen = "
+#define PLEN_PREFIX	"Plen = "
+#define IVLEN_PREFIX	"Nlen = "
+#define DIGESTL_PREFIX	"Tlen = "
+
+#define COUNT_STR	"Count = "
+#define KEY_STR		"Key = "
+#define IV_STR		"Nonce = "
+#define PT_STR		"Payload = "
+#define CT_STR		"CT = "
+#define AAD_STR		"Adata = "
+#define POS_NEG_STR	"Result = "
+
+#define POS_KEYWORD	"Pass"
+#define NEG_KEYWORD	"Fail"
+
+static int
+parser_dvpt_interim(const char *key, char *src, struct fips_val *val)
+{
+	char *tmp, c, value[10];
+	char num_pattern[] = "0123456789";
+	int i = 0;
+
+	memset(value, 0, 10);
+
+	tmp = strstr(src, key);
+	if (!tmp)
+		return -1;
+
+	tmp += strlen(key);
+
+	c = tmp[0];
+
+	while (strchr(num_pattern, c) && i < 10) {
+		value[i++] = c;
+		c = tmp[i];
+	}
+
+	return parser_read_uint32_val("", value, val);
+}
+
+static int
+parse_dvpt_ct_hex_str(const char *key, char *src, struct fips_val *val)
+{
+	int ret;
+
+	val->len = vec.pt.len;
+
+	ret = parse_uint8_known_len_hex_str(key, src, val);
+	if (ret < 0)
+		return ret;
+
+	src += strlen(key) + val->len * 2;
+
+	ret = parse_uint8_known_len_hex_str("", src, &vec.aead.digest);
+	if (ret < 0) {
+		rte_free(val->val);
+		memset(val, 0, sizeof(*val));
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+parse_uint8_ccm_aad_str(const char *key, char *src, struct fips_val *val)
+{
+	uint32_t len = val->len, j;
+
+	src += strlen(key);
+
+	/* CCM aad requires 18 bytes padding before the real content */
+	val->val = rte_zmalloc(NULL, len + 18, 0);
+	if (!val->val)
+		return -1;
+
+	for (j = 0; j < len; j++) {
+		char byte[3] = {src[j * 2], src[j * 2 + 1], '\0'};
+
+		if (parser_read_uint8_hex(&val->val[j + 18], byte) < 0) {
+			rte_free(val->val);
+			memset(val, 0, sizeof(*val));
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+struct fips_test_callback ccm_vnt_vec[] = {
+		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
+		{AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad},
+		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vnt_interim_vec[] = {
+		{ALEN_PREFIX, parser_read_uint32_val, &vec.aead.aad},
+		{PLEN_PREFIX, parser_read_uint32_val, &vec.pt},
+		{DIGESTL_PREFIX, parser_read_uint32_val, &vec.aead.digest},
+		{IVLEN_PREFIX, parser_read_uint32_val, &vec.iv},
+		{KEY_STR, parse_uint8_hex_str, &vec.aead.key},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vtt_vec[] = {
+		{AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad},
+		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vtt_interim_vec[] = {
+		{ALEN_PREFIX, parser_read_uint32_val, &vec.aead.aad},
+		{PLEN_PREFIX, parser_read_uint32_val, &vec.pt},
+		{IVLEN_PREFIX, parser_read_uint32_val, &vec.iv},
+		{DIGESTL_PREFIX, parser_read_uint32_val, &vec.aead.digest},
+		{KEY_STR, parse_uint8_hex_str, &vec.aead.key},
+		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vadt_vec[] = {
+		{AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad},
+		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vadt_interim_vec[] = {
+		{PLEN_PREFIX, parser_read_uint32_val, &vec.pt},
+		{IVLEN_PREFIX, parser_read_uint32_val, &vec.iv},
+		{ALEN_PREFIX, parser_read_uint32_val, &vec.aead.aad},
+		{DIGESTL_PREFIX, parser_read_uint32_val, &vec.aead.digest},
+		{KEY_STR, parse_uint8_hex_str, &vec.aead.key},
+		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vpt_vec[] = {
+		{AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad},
+		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vpt_interim_vec[] = {
+		{ALEN_PREFIX, parser_read_uint32_val, &vec.aead.aad},
+		{IVLEN_PREFIX, parser_read_uint32_val, &vec.iv},
+		{DIGESTL_PREFIX, parser_read_uint32_val, &vec.aead.digest},
+		{PLEN_PREFIX, parser_read_uint32_val, &vec.pt},
+		{KEY_STR, parse_uint8_hex_str, &vec.aead.key},
+		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_dvpt_vec[] = {
+		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
+		{AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad},
+		{CT_STR, parse_dvpt_ct_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_dvpt_interim_vec[] = {
+		{ALEN_PREFIX, parser_dvpt_interim, &vec.aead.aad},
+		{PLEN_PREFIX, parser_dvpt_interim, &vec.pt},
+		{IVLEN_PREFIX, parser_dvpt_interim, &vec.iv},
+		{DIGESTL_PREFIX, parser_dvpt_interim, &vec.aead.digest},
+		{KEY_STR, parse_uint8_hex_str, &vec.aead.key},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct ccm_test_types {
+	const char *str;
+	uint32_t type;
+	const struct fips_test_callback *cb;
+	const struct fips_test_callback *cb_interim;
+	enum fips_test_op op;
+} ctt[] = {
+		{DVPT_STR, CCM_DVPT, ccm_dvpt_vec, ccm_dvpt_interim_vec,
+			FIPS_TEST_DEC_AUTH_VERIF},
+		{VPT_STR, CCM_VPT, ccm_vpt_vec, ccm_vpt_interim_vec,
+			FIPS_TEST_ENC_AUTH_GEN},
+		{VADT_STR, CCM_VADT, ccm_vadt_vec, ccm_vadt_interim_vec,
+			FIPS_TEST_ENC_AUTH_GEN},
+		{VNT_STR, CCM_VNT, ccm_vnt_vec, ccm_vnt_interim_vec,
+			FIPS_TEST_ENC_AUTH_GEN},
+		{VTT_STR, CCM_VTT, ccm_vtt_vec, ccm_vtt_interim_vec,
+			FIPS_TEST_ENC_AUTH_GEN},
+};
+
+static int
+parse_test_ccm_writeback(struct fips_val *val)
+{
+	struct fips_val tmp_val;
+
+	switch (info.interim_info.ccm_data.test_type) {
+	case CCM_DVPT:
+		fprintf(info.fp_wr, "%s", POS_NEG_STR);
+		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS) {
+			fprintf(info.fp_wr, "%s\n", POS_KEYWORD);
+			fprintf(info.fp_wr, "%s", PT_STR);
+
+			tmp_val.val = val->val;
+			tmp_val.len = vec.pt.len;
+
+			if (tmp_val.len == 0)
+				fprintf(info.fp_wr, "00\n");
+			else
+				parse_write_hex_str(&tmp_val);
+		} else
+			fprintf(info.fp_wr, "%s\n", NEG_KEYWORD);
+
+		break;
+
+	case CCM_VADT:
+	case CCM_VNT:
+	case CCM_VPT:
+	case CCM_VTT:
+		fprintf(info.fp_wr, "%s", CT_STR);
+
+		parse_write_hex_str(val);
+
+		break;
+
+	}
+
+	return 0;
+}
+
+int
+parse_test_ccm_init(void)
+{
+
+	uint32_t i;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		char *line = info.vec[i];
+		uint32_t j;
+
+		for (j = 0; j < RTE_DIM(ctt); j++)
+			if (strstr(line, ctt[j].str)) {
+				info.interim_info.ccm_data.test_type =
+						ctt[j].type;
+				info.callbacks = ctt[j].cb;
+				info.interim_callbacks = ctt[j].cb_interim;
+				info.op = ctt[j].op;
+				break;
+		}
+	}
+
+	info.parse_writeback = parse_test_ccm_writeback;
+
+	return 0;
+}
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index e953f3e..0a7e75f 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -470,7 +470,10 @@ prepare_aead_op(void)
 	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
 	rte_pktmbuf_reset(env.mbuf);
 
-	memcpy(iv, vec.iv.val, vec.iv.len);
+	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);
 
 	sym->m_src = env.mbuf;
 	sym->aead.data.offset = 0;
@@ -726,6 +729,52 @@ prepare_cmac_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_ccm_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_aead_xform *aead_xform = &xform->aead;
+
+	xform->type = RTE_CRYPTO_SYM_XFORM_AEAD;
+
+	aead_xform->algo = RTE_CRYPTO_AEAD_AES_CCM;
+	aead_xform->aad_length = vec.aead.aad.len;
+	aead_xform->digest_length = vec.aead.digest.len;
+	aead_xform->iv.offset = IV_OFF;
+	aead_xform->iv.length = vec.iv.len;
+	aead_xform->key.data = vec.aead.key.val;
+	aead_xform->key.length = vec.aead.key.len;
+	aead_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_AEAD_OP_ENCRYPT :
+			RTE_CRYPTO_AEAD_OP_DECRYPT;
+
+	cap_idx.algo.aead = aead_xform->algo;
+	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
+
+	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_aead(cap,
+			aead_xform->key.length,
+			aead_xform->digest_length, aead_xform->aad_length,
+			aead_xform->iv.length) != 0) {
+		RTE_LOG(ERR, USER1,
+			"PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n",
+				info.device_name, aead_xform->key.length,
+				aead_xform->digest_length,
+				aead_xform->aad_length,
+				aead_xform->iv.length);
+		return -EPERM;
+	}
+
+	return 0;
+}
+
 static void
 get_writeback_data(struct fips_val *val)
 {
@@ -1091,6 +1140,11 @@ init_test_ops(void)
 		test_ops.prepare_xform = prepare_cmac_xform;
 		test_ops.test = fips_generic_test;
 		break;
+	case FIPS_TEST_ALGO_AES_CCM:
+		test_ops.prepare_op = prepare_aead_op;
+		test_ops.prepare_xform = prepare_ccm_xform;
+		test_ops.test = fips_generic_test;
+		break;
 	default:
 		return -1;
 	}
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
index a0d38fa..498c9ba 100644
--- a/examples/fips_validation/meson.build
+++ b/examples/fips_validation/meson.build
@@ -15,5 +15,6 @@ sources = files(
 	'fips_validation_tdes.c',
 	'fips_validation_gcm.c',
 	'fips_validation_cmac.c',
+	'fips_validation_ccm.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v6 8/8] doc: add fips validation application guide
  2018-10-26 11:07   ` [dpdk-dev] [PATCH v6 " Marko Kovacevic
                       ` (6 preceding siblings ...)
  2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 7/8] examples/fips_validation: support CCM parsing Marko Kovacevic
@ 2018-10-26 11:07     ` Marko Kovacevic
  2018-11-02  9:17     ` [dpdk-dev] [PATCH v6 0/8] FIPS validation capability Akhil Goyal
  2018-11-02  9:55     ` [dpdk-dev] [PATCH v7 " Kovacevic, Marko
  9 siblings, 0 replies; 52+ messages in thread
From: Marko Kovacevic @ 2018-10-26 11:07 UTC (permalink / raw)
  To: akhil.goyal; +Cc: dev, roy.fan.zhang, arkadiuszx.kusztal, Kovacevic, Marko

From: "Kovacevic, Marko" <marko.kovacevic@intel.com>

Document explains how to run the fips sample app
and instructions users need to parser all the request
files and generate the response files.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 doc/guides/rel_notes/release_18_11.rst       |   5 +
 doc/guides/sample_app_ug/fips_validation.rst | 132 +++++++++++++++++++++++++++
 doc/guides/sample_app_ug/index.rst           |   1 +
 3 files changed, 138 insertions(+)
 create mode 100644 doc/guides/sample_app_ug/fips_validation.rst

diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index 04f3745..c085d4b 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -198,6 +198,11 @@ New Features
   this application doesn't need to launch dedicated worker threads for vhost
   enqueue/dequeue operations.
 
+* **Added Cryptodev Fips Validation Example Application.**
+
+  Added an example application to parse and perform symmetric cryptography
+  computation to the NIST Cryptographic Algorithm Validation Program (CAVP)
+  test vectors.
 
 API Changes
 -----------
diff --git a/doc/guides/sample_app_ug/fips_validation.rst b/doc/guides/sample_app_ug/fips_validation.rst
new file mode 100644
index 0000000..aeacfac
--- /dev/null
+++ b/doc/guides/sample_app_ug/fips_validation.rst
@@ -0,0 +1,132 @@
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(c) 2018 Intel Corporation.
+
+Federal Information Processing Standards (FIPS) CryptoDev Validation
+====================================================================
+
+Overview
+--------
+
+Federal Information Processing Standards (FIPS) are publicly announced standards
+developed by the United States federal government for use in computer systems by
+non-military government agencies and government contractors.
+
+This application is used to parse and perform symmetric cryptography
+computation to the NIST Cryptographic Algorithm Validation Program (CAVP) test
+vectors.
+
+For an algorithm implementation to be listed on a cryptographic module
+validation certificate as an Approved security function, the algorithm
+implementation must meet all the requirements of FIPS 140-2 and must
+successfully complete the cryptographic algorithm validation process.
+
+Limitations
+-----------
+
+* Only NIST CAVP request files are parsed by this application.
+* The version of request file supported is ``CAVS 21.0``
+* If the header comment in a ``.req`` file does not contain a Algo tag
+  i.e ``AES,TDES,GCM`` you need to manually add it into the header comment for
+  example::
+
+      # VARIABLE KEY - KAT for CBC / # TDES VARIABLE KEY - KAT for CBC
+
+* The application does not supply the test vectors. The user is expected to
+  obtain the test vector files from `NIST
+  <https://csrc.nist.gov/projects/cryptographic-algorithm-validation-
+  program/block-ciphers>`_ website. To obtain the ``.req`` files you need to
+  email a person from the NIST website and pay for the ``.req`` files.
+  The ``.rsp`` files from the site can be used to validate and compare with
+  the ``.rsp`` files created by the FIPS application.
+
+* Supported test vectors
+    * AES-CBC (128,192,256) - GFSbox, KeySbox, MCT, MMT
+    * AES-GCM (128,192,256) - EncryptExtIV, Decrypt
+    * AES-CCM (128) - VADT, VNT, VPT, VTT, DVPT
+    * AES-CMAC (128) - Generate, Verify
+    * HMAC (SHA1, SHA224, SHA256, SHA384, SHA512)
+    * TDES-CBC (1 Key, 2 Keys, 3 Keys) - MMT, Monte, Permop, Subkey, Varkey,
+      VarText
+
+Application Information
+-----------------------
+
+If a ``.req`` is used as the input file after the application is finished
+running it will generate a response file or ``.rsp``. Differences between the
+two files are, the ``.req`` file has missing information for instance if doing
+encryption you will not have the cipher text and that will be generated in the
+response file. Also if doing decryption it will not have the plain text until it
+finished the work and in the response file it will be added onto the end of each
+operation.
+
+The application can be run with a ``.rsp`` file and what the outcome of that
+will be is it will add a extra line in the generated ``.rsp`` which should be
+the same as the ``.rsp`` used to run the application, this is useful for
+validating if the application has done the operation correctly.
+
+
+Compiling the Application
+-------------------------
+
+* Compile Application
+
+    .. code-block:: console
+
+         make -C examples/fips_validation
+
+*  Run ``dos2unix`` on the request files
+
+    .. code-block:: console
+
+         dos2unix AES/req/*
+         dos2unix AES_GCM/req/*
+         dos2unix CCM/req/*
+         dos2unix CMAC/req/*
+         dos2unix HMAC/req/*
+         dos2unix TDES/req/*
+
+Running the Application
+-----------------------
+
+The application requires a number of command line options:
+
+    .. code-block:: console
+
+         ./fips_validation [EAL options]
+         -- --req-file FILE_PATH/FOLDER_PATH
+         --rsp-file FILE_PATH/FOLDER_PATH
+         [--cryptodev DEVICE_NAME] [--cryptodev-id ID] [--path-is-folder]
+
+where,
+  * req-file: The path of the request file or folder, separated by
+    ``path-is-folder`` option.
+
+  * rsp-file: The path that the response file or folder is stored. separated by
+    ``path-is-folder`` option.
+
+  * cryptodev: The name of the target DPDK Crypto device to be validated.
+
+  * cryptodev-id: The id of the target DPDK Crypto device to be validated.
+
+  * path-is-folder: If presented the application expects req-file and rsp-file
+    are folder paths.
+
+
+To run the application in linuxapp environment to test one AES FIPS test data
+file for crypto_aesni_mb PMD, issue the command:
+
+.. code-block:: console
+
+    $ ./fips_validation --vdev crypto_aesni_mb --
+    --req-file /PATH/TO/REQUEST/FILE.req --rsp-file ./PATH/TO/RESPONSE/FILE.rsp
+    --cryptodev crypto_aesni_mb
+
+To run the application in linuxapp environment to test all AES-GCM FIPS test
+data files in one folder for crypto_aesni_gcm PMD, issue the command:
+
+.. code-block:: console
+
+    $ ./fips_validation --vdev crypto_aesni_gcm0 --
+    --req-file /PATH/TO/REQUEST/FILE/FOLDER/
+    --rsp-file ./PATH/TO/RESPONSE/FILE/FOLDER/
+    --cryptodev-id 0 --path-is-folder
diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst
index 74b12af..65c12d9 100644
--- a/doc/guides/sample_app_ug/index.rst
+++ b/doc/guides/sample_app_ug/index.rst
@@ -57,6 +57,7 @@ Sample Applications User Guides
     performance_thread
     ipsec_secgw
     bbdev_app
+    fips_validation
 
 **Figures**
 
-- 
2.9.5

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

* Re: [dpdk-dev] [PATCH v6 0/8] FIPS validation capability
  2018-10-26 11:07   ` [dpdk-dev] [PATCH v6 " Marko Kovacevic
                       ` (7 preceding siblings ...)
  2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 8/8] doc: add fips validation application guide Marko Kovacevic
@ 2018-11-02  9:17     ` Akhil Goyal
  2018-11-02  9:34       ` Kovacevic, Marko
  2018-11-02  9:55     ` [dpdk-dev] [PATCH v7 " Kovacevic, Marko
  9 siblings, 1 reply; 52+ messages in thread
From: Akhil Goyal @ 2018-11-02  9:17 UTC (permalink / raw)
  To: Marko Kovacevic; +Cc: dev, roy.fan.zhang, arkadiuszx.kusztal

Hi Marko,

I can see a compilation issue in the app.

/home/akhil/netperf/dpdk_up/dpdk-next-crypto/examples/fips_validation/fips_validation.c: 
In function 'get_file_line':
/home/akhil/netperf/dpdk_up/dpdk-next-crypto/examples/fips_validation/fips_validation.c:31:25: 
error: comparison is always true due to limited range of data type 
[-Werror=type-limits]
   while ((c = fgetc(fp)) != EOF) {
                          ^~
/home/akhil/netperf/dpdk_up/dpdk-next-crypto/examples/fips_validation/fips_validation.c:39:8: 
error: comparison is always false due to limited range of data type 
[-Werror=type-limits]
   if (c == EOF)
         ^~
cc1: all warnings being treated as errors
/home/akhil/netperf/dpdk_up/dpdk-next-crypto/mk/internal/rte.compile-pre.mk:114: 
recipe for target 'fips_validation.o' failed


On 10/26/2018 4:37 PM, Marko Kovacevic wrote:
> From: "Kovacevic, Marko" <marko.kovacevic@intel.com>
>
> This sample application is made for the purpose so that users of DPDK
> who wish to get FIPS certification for their platforms, this sample app enables
> users to parse test vectors that is gotten from NIST and be able to get
> a generated response file which they can then verify and be sure their
> system will pass FIPS certification.
>
>
> Marko Kovacevic (8):
> v6:
>    - Added MAINTAINER file into different patch
>    - Udpated documentation
>    - Changed app name and file location
>    - Fixed memory leak in TDES
>    - Changed patch titles
>    - Made other changes from comments
> v5:
>    - Changed patch titles
>    - Added MAINTAINERS File
>    - Removed bus_pci Dependency
>    - Updated documentation
>    - Changed app name
> v4:
> - Added Limitation
> - Changed TDES BLOCK SIZE from 16 -> 8
>    as DES block size is 64bits (main.c)
> v3:
> - Fixed a no-testing bug
> - Fixed some code style issue
>
> v2:
> - Refactor the code.
> - Move the code from test to sample applcation
>
> Kovacevic, Marko (8):
>    examples/fips_validation: add cryptodev fips compliant application
>    examples/fips_validation: support AES parsing
>    examples/fips_validation: support HMAC parsing
>    examples/fips_validation: support TDES parsing
>    examples/fips_validation: support GCM parsing
>    examples/fips_validation: support CMAC parsing
>    examples/fips_validation: support CCM parsing
>    doc: add fips validation application guide
>
>   MAINTAINERS                                     |    4 +
>   doc/guides/rel_notes/release_18_11.rst          |    5 +
>   doc/guides/sample_app_ug/fips_validation.rst    |  132 +++
>   doc/guides/sample_app_ug/index.rst              |    1 +
>   examples/fips_validation/Makefile               |   75 ++
>   examples/fips_validation/fips_validation.c      |  593 +++++++++++
>   examples/fips_validation/fips_validation.h      |  233 +++++
>   examples/fips_validation/fips_validation_aes.c  |  188 ++++
>   examples/fips_validation/fips_validation_ccm.c  |  272 +++++
>   examples/fips_validation/fips_validation_cmac.c |  116 +++
>   examples/fips_validation/fips_validation_gcm.c  |  125 +++
>   examples/fips_validation/fips_validation_hmac.c |  105 ++
>   examples/fips_validation/fips_validation_tdes.c |  264 +++++
>   examples/fips_validation/main.c                 | 1221 +++++++++++++++++++++++
>   examples/fips_validation/meson.build            |   20 +
>   15 files changed, 3354 insertions(+)
>   create mode 100644 doc/guides/sample_app_ug/fips_validation.rst
>   create mode 100644 examples/fips_validation/Makefile
>   create mode 100644 examples/fips_validation/fips_validation.c
>   create mode 100644 examples/fips_validation/fips_validation.h
>   create mode 100644 examples/fips_validation/fips_validation_aes.c
>   create mode 100644 examples/fips_validation/fips_validation_ccm.c
>   create mode 100644 examples/fips_validation/fips_validation_cmac.c
>   create mode 100644 examples/fips_validation/fips_validation_gcm.c
>   create mode 100644 examples/fips_validation/fips_validation_hmac.c
>   create mode 100644 examples/fips_validation/fips_validation_tdes.c
>   create mode 100644 examples/fips_validation/main.c
>   create mode 100644 examples/fips_validation/meson.build
>


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

* Re: [dpdk-dev] [PATCH v6 0/8] FIPS validation capability
  2018-11-02  9:17     ` [dpdk-dev] [PATCH v6 0/8] FIPS validation capability Akhil Goyal
@ 2018-11-02  9:34       ` Kovacevic, Marko
  0 siblings, 0 replies; 52+ messages in thread
From: Kovacevic, Marko @ 2018-11-02  9:34 UTC (permalink / raw)
  To: Akhil Goyal; +Cc: dev, Zhang, Roy Fan, Kusztal, ArkadiuszX

> Hi Marko,
> 
> I can see a compilation issue in the app.
> 
> /home/akhil/netperf/dpdk_up/dpdk-next-
> crypto/examples/fips_validation/fips_validation.c:
> In function 'get_file_line':
> /home/akhil/netperf/dpdk_up/dpdk-next-
> crypto/examples/fips_validation/fips_validation.c:31:25:
> error: comparison is always true due to limited range of data type [-
> Werror=type-limits]
>    while ((c = fgetc(fp)) != EOF) {
>                           ^~
> /home/akhil/netperf/dpdk_up/dpdk-next-
> crypto/examples/fips_validation/fips_validation.c:39:8:
> error: comparison is always false due to limited range of data type [-
> Werror=type-limits]
>    if (c == EOF)
>          ^~
> cc1: all warnings being treated as errors
> /home/akhil/netperf/dpdk_up/dpdk-next-crypto/mk/internal/rte.compile-
> pre.mk:114:
> recipe for target 'fips_validation.o' failed
> 

That didn’t pop up for me on my side when compiling but I see the error sending a fix now.

Thanks Akhil.

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

* [dpdk-dev] [PATCH v7 0/8] FIPS validation capability
  2018-10-26 11:07   ` [dpdk-dev] [PATCH v6 " Marko Kovacevic
                       ` (8 preceding siblings ...)
  2018-11-02  9:17     ` [dpdk-dev] [PATCH v6 0/8] FIPS validation capability Akhil Goyal
@ 2018-11-02  9:55     ` Kovacevic, Marko
  2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 1/8] examples/fips_validation: add cryptodev fips compliant application Kovacevic, Marko
                         ` (8 more replies)
  9 siblings, 9 replies; 52+ messages in thread
From: Kovacevic, Marko @ 2018-11-02  9:55 UTC (permalink / raw)
  To: akhil.goyal; +Cc: dev, roy.fan.zhang, arkadiuszx.kusztal, Kovacevic, Marko

This sample application is made for the purpose so that users of DPDK
who wish to get FIPS certification for their platforms, this sample app enables
users to parse test vectors that is gotten from NIST and be able to get
a generated response file which they can then verify and be sure their
system will pass FIPS certification.

Kovacevic, Marko (8):
v7:
  - Fixed compilation issue.
v6:
  - Added MAINTAINER file into different patch
  - Udpated documentation
  - Changed app name and file location
  - Fixed memory leak in TDES
  - Changed patch titles
  - Made other changes from comments
v5:
  - Changed patch titles
  - Added MAINTAINERS File
  - Removed bus_pci Dependency
  - Updated documentation
  - Changed app name
v4:
- Added Limitation
- Changed TDES BLOCK SIZE from 16 -> 8
  as DES block size is 64bits (main.c)
v3:
- Fixed a no-testing bug
- Fixed some code style issue

v2:
- Refactor the code.
- Move the code from test to sample applcation

  examples/fips_validation: add cryptodev fips compliant application
  examples/fips_validation: support AES parsing
  examples/fips_validation: support HMAC parsing
  examples/fips_validation: support TDES parsing
  examples/fips_validation: support GCM parsing
  examples/fips_validation: support CMAC parsing
  examples/fips_validation: support CCM parsing
  doc: add fips validation application guide

 MAINTAINERS                                     |    4 +
 doc/guides/rel_notes/release_18_11.rst          |    5 +
 doc/guides/sample_app_ug/fips_validation.rst    |  132 +++
 doc/guides/sample_app_ug/index.rst              |    1 +
 examples/fips_validation/Makefile               |   75 ++
 examples/fips_validation/fips_validation.c      |  595 +++++++++++
 examples/fips_validation/fips_validation.h      |  233 +++++
 examples/fips_validation/fips_validation_aes.c  |  188 ++++
 examples/fips_validation/fips_validation_ccm.c  |  272 +++++
 examples/fips_validation/fips_validation_cmac.c |  116 +++
 examples/fips_validation/fips_validation_gcm.c  |  125 +++
 examples/fips_validation/fips_validation_hmac.c |  105 ++
 examples/fips_validation/fips_validation_tdes.c |  264 +++++
 examples/fips_validation/main.c                 | 1221 +++++++++++++++++++++++
 examples/fips_validation/meson.build            |   20 +
 15 files changed, 3356 insertions(+)
 create mode 100644 doc/guides/sample_app_ug/fips_validation.rst
 create mode 100644 examples/fips_validation/Makefile
 create mode 100644 examples/fips_validation/fips_validation.c
 create mode 100644 examples/fips_validation/fips_validation.h
 create mode 100644 examples/fips_validation/fips_validation_aes.c
 create mode 100644 examples/fips_validation/fips_validation_ccm.c
 create mode 100644 examples/fips_validation/fips_validation_cmac.c
 create mode 100644 examples/fips_validation/fips_validation_gcm.c
 create mode 100644 examples/fips_validation/fips_validation_hmac.c
 create mode 100644 examples/fips_validation/fips_validation_tdes.c
 create mode 100644 examples/fips_validation/main.c
 create mode 100644 examples/fips_validation/meson.build

-- 
2.9.5

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

* [dpdk-dev] [PATCH v7 1/8] examples/fips_validation: add cryptodev fips compliant application
  2018-11-02  9:55     ` [dpdk-dev] [PATCH v7 " Kovacevic, Marko
@ 2018-11-02  9:55       ` Kovacevic, Marko
  2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 2/8] examples/fips_validation: support AES parsing Kovacevic, Marko
                         ` (7 subsequent siblings)
  8 siblings, 0 replies; 52+ messages in thread
From: Kovacevic, Marko @ 2018-11-02  9:55 UTC (permalink / raw)
  To: akhil.goyal; +Cc: dev, roy.fan.zhang, arkadiuszx.kusztal, Kovacevic, Marko

Added FIPS application into the examples to allow
users to use a simple sample app to validate
their systems and be able to get FIPS certification.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 MAINTAINERS                                |   4 +
 examples/fips_validation/Makefile          |  69 ++++
 examples/fips_validation/fips_validation.c | 564 +++++++++++++++++++++++++++++
 examples/fips_validation/fips_validation.h | 149 ++++++++
 examples/fips_validation/main.c            | 388 ++++++++++++++++++++
 examples/fips_validation/meson.build       |  14 +
 6 files changed, 1188 insertions(+)
 create mode 100644 examples/fips_validation/Makefile
 create mode 100644 examples/fips_validation/fips_validation.c
 create mode 100644 examples/fips_validation/fips_validation.h
 create mode 100644 examples/fips_validation/main.c
 create mode 100644 examples/fips_validation/meson.build

diff --git a/MAINTAINERS b/MAINTAINERS
index e60379d..f52b8b9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1343,3 +1343,7 @@ F: examples/tep_termination/
 F: examples/vmdq/
 F: examples/vmdq_dcb/
 F: doc/guides/sample_app_ug/vmdq_dcb_forwarding.rst
+
+M: Marko Kovacevic <marko.kovacevic@intel.com>
+F: examples/fips_validation
+F: doc/guides/sample_app_ug/fips_validation.rst
diff --git a/examples/fips_validation/Makefile b/examples/fips_validation/Makefile
new file mode 100644
index 0000000..59d56c7
--- /dev/null
+++ b/examples/fips_validation/Makefile
@@ -0,0 +1,69 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Intel Corporation
+
+# binary name
+APP = fips_validation
+
+# all source are stored in SRCS-y
+SRCS-y := fips_validation.c
+SRCS-y += main.c
+
+# Build using pkg-config variables if possible
+$(shell pkg-config --exists libdpdk)
+ifeq ($(.SHELLSTATUS),0)
+
+all: shared
+.PHONY: shared static
+shared: build/$(APP)-shared
+	ln -sf $(APP)-shared build/$(APP)
+static: build/$(APP)-static
+	ln -sf $(APP)-static build/$(APP)
+
+PC_FILE := $(shell pkg-config --path libdpdk)
+CFLAGS += -O3 $(shell pkg-config --cflags libdpdk)
+LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk)
+LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk)
+
+build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
+	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
+
+build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build
+	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC)
+
+build:
+	@mkdir -p $@
+
+.PHONY: clean
+clean:
+	rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared
+	rmdir --ignore-fail-on-non-empty build
+
+else
+
+ifeq ($(RTE_SDK),)
+$(error "Please define RTE_SDK environment variable")
+endif
+
+# Default target, can be overridden by command line or environment
+RTE_TARGET ?= x86_64-native-linuxapp-gcc
+
+INC += $(sort $(wildcard *.h))
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+CFLAGS += $(WERROR_FLAGS)
+
+# workaround for a gcc bug with noreturn attribute
+# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603
+ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
+CFLAGS_main.o += -Wno-return-type
+endif
+
+CFLAGS += -DALLOW_EXPERIMENTAL_API
+CFLAGS += -I$(SRCDIR)
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+include $(RTE_SDK)/mk/rte.extapp.mk
+
+endif
diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
new file mode 100644
index 0000000..58a3c1b
--- /dev/null
+++ b/examples/fips_validation/fips_validation.c
@@ -0,0 +1,564 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <rte_string_fns.h>
+#include <rte_cryptodev.h>
+#include <rte_malloc.h>
+
+#include "fips_validation.h"
+
+#define skip_white_spaces(pos)			\
+({						\
+	__typeof__(pos) _p = (pos);		\
+	for ( ; isspace(*_p); _p++)		\
+		;				\
+	_p;					\
+})
+
+static int
+get_file_line(void)
+{
+	FILE *fp = info.fp_rd;
+	char *line = info.one_line_text;
+	int ret;
+	uint32_t loc = 0;
+
+	memset(line, 0, MAX_LINE_CHAR);
+	while ((ret = fgetc(fp)) != EOF) {
+		char c = (char)ret;
+
+		if (loc >= MAX_LINE_CHAR - 1)
+			return -ENOMEM;
+		if (c == '\n')
+			break;
+		line[loc++] = c;
+	}
+
+	if (ret == EOF)
+		return -EOF;
+
+	return 0;
+}
+
+int
+fips_test_fetch_one_block(void)
+{
+	size_t size;
+	int ret = 0;
+	uint32_t i;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		free(info.vec[i]);
+		info.vec[i] = NULL;
+	}
+
+	i = 0;
+	do {
+		if (i >= MAX_LINE_PER_VECTOR) {
+			ret = -ENOMEM;
+			goto error_exit;
+		}
+
+		ret = get_file_line();
+		size = strlen(info.one_line_text);
+		if (size == 0)
+			break;
+
+		info.vec[i] = calloc(1, size + 5);
+		if (info.vec[i] == NULL)
+			goto error_exit;
+
+		strlcpy(info.vec[i], info.one_line_text, size + 1);
+		i++;
+	} while (ret == 0);
+
+	info.nb_vec_lines = i;
+
+	return ret;
+
+error_exit:
+	for (i = 0; i < MAX_LINE_PER_VECTOR; i++)
+		if (info.vec[i] != NULL) {
+			free(info.vec[i]);
+			info.vec[i] = NULL;
+		}
+
+	info.nb_vec_lines = 0;
+
+	return -ENOMEM;
+}
+
+static int
+fips_test_parse_header(void)
+{
+	uint32_t i;
+	char *tmp;
+	int ret;
+	time_t t = time(NULL);
+	struct tm *tm_now = localtime(&t);
+
+	ret = fips_test_fetch_one_block();
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+
+		tmp = strstr(info.vec[i], "# Config info for ");
+		if (tmp != NULL) {
+			fprintf(info.fp_wr, "%s%s\n", "# Config info for DPDK Cryptodev ",
+					info.device_name);
+			continue;
+		}
+
+		tmp = strstr(info.vec[i], "#  HMAC information for ");
+		if (tmp != NULL) {
+			fprintf(info.fp_wr, "%s%s\n", "#  HMAC information for "
+				"DPDK Cryptodev ",
+				info.device_name);
+			continue;
+		}
+
+		tmp = strstr(info.vec[i], "# Config Info for : ");
+		if (tmp != NULL) {
+
+			fprintf(info.fp_wr, "%s%s\n", "# Config Info for DPDK Cryptodev : ",
+					info.device_name);
+			continue;
+		}
+
+		tmp = strstr(info.vec[i], "# information for ");
+		if (tmp != NULL) {
+
+			char tmp_output[128] = {0};
+
+			strlcpy(tmp_output, info.vec[i], tmp - info.vec[i] + 1);
+
+			fprintf(info.fp_wr, "%s%s%s\n", tmp_output,
+					"information for DPDK Cryptodev ",
+					info.device_name);
+			continue;
+		}
+
+		tmp = strstr(info.vec[i], " test information for ");
+		if (tmp != NULL) {
+			char tmp_output[128] = {0};
+
+			strlcpy(tmp_output, info.vec[i], tmp - info.vec[i] + 1);
+
+			fprintf(info.fp_wr, "%s%s%s\n", tmp_output,
+					"test information for DPDK Cryptodev ",
+					info.device_name);
+			continue;
+		}
+
+		if (i == info.nb_vec_lines - 1) {
+			/** update the time as current time, write to file */
+			fprintf(info.fp_wr, "%s%s\n", "# Generated on ",
+					asctime(tm_now));
+			continue;
+		}
+
+		/* to this point, no field need to update,
+		 *  only copy to rsp file
+		 */
+		fprintf(info.fp_wr, "%s\n", info.vec[i]);
+	}
+
+	return 0;
+}
+
+static int
+parse_file_type(const char *path)
+{
+	const char *tmp = path + strlen(path) - 3;
+
+	if (strstr(tmp, REQ_FILE_PERFIX))
+		info.file_type = FIPS_TYPE_REQ;
+	else if (strstr(tmp, RSP_FILE_PERFIX))
+		info.file_type = FIPS_TYPE_RSP;
+	else if (strstr(path, FAX_FILE_PERFIX))
+		info.file_type = FIPS_TYPE_FAX;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+int
+fips_test_init(const char *req_file_path, const char *rsp_file_path,
+		const char *device_name)
+{
+	if (strcmp(req_file_path, rsp_file_path) == 0) {
+		RTE_LOG(ERR, USER1, "File paths cannot be the same\n");
+		return -EINVAL;
+	}
+
+	fips_test_clear();
+
+	info.algo = FIPS_TEST_ALGO_MAX;
+	if (parse_file_type(req_file_path) < 0) {
+		RTE_LOG(ERR, USER1, "File %s type not supported\n",
+				req_file_path);
+		return -EINVAL;
+	}
+
+	info.fp_rd = fopen(req_file_path, "r");
+	if (!info.fp_rd) {
+		RTE_LOG(ERR, USER1, "Cannot open file %s\n", req_file_path);
+		return -EINVAL;
+	}
+
+	info.fp_wr = fopen(rsp_file_path, "w");
+	if (!info.fp_wr) {
+		RTE_LOG(ERR, USER1, "Cannot open file %s\n", rsp_file_path);
+		return -EINVAL;
+	}
+
+	info.one_line_text = calloc(1, MAX_LINE_CHAR);
+	if (!info.one_line_text) {
+		RTE_LOG(ERR, USER1, "Insufficient memory\n");
+		return -ENOMEM;
+	}
+
+	strlcpy(info.device_name, device_name, sizeof(info.device_name));
+
+	if (fips_test_parse_header() < 0) {
+		RTE_LOG(ERR, USER1, "Failed parsing header\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+void
+fips_test_clear(void)
+{
+	if (info.fp_rd)
+		fclose(info.fp_rd);
+	if (info.fp_wr)
+		fclose(info.fp_wr);
+	if (info.one_line_text)
+		free(info.one_line_text);
+	if (info.nb_vec_lines) {
+		uint32_t i;
+
+		for (i = 0; i < info.nb_vec_lines; i++)
+			free(info.vec[i]);
+	}
+
+	memset(&info, 0, sizeof(info));
+}
+
+int
+fips_test_parse_one_case(void)
+{
+	uint32_t i, j = 0;
+	uint32_t is_interim = 0;
+	int ret;
+
+	if (info.interim_callbacks) {
+		for (i = 0; i < info.nb_vec_lines; i++) {
+			for (j = 0; info.interim_callbacks[j].key != NULL; j++)
+				if (strstr(info.vec[i],
+					info.interim_callbacks[j].key)) {
+					is_interim = 1;
+
+					ret = info.interim_callbacks[j].cb(
+						info.interim_callbacks[j].key,
+						info.vec[i],
+						info.interim_callbacks[j].val);
+					if (ret < 0)
+						return ret;
+				}
+		}
+	}
+
+	if (is_interim) {
+		for (i = 0; i < info.nb_vec_lines; i++)
+			fprintf(info.fp_wr, "%s\n", info.vec[i]);
+		fprintf(info.fp_wr, "\n");
+		return 1;
+	}
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		for (j = 0; info.callbacks[j].key != NULL; j++)
+			if (strstr(info.vec[i], info.callbacks[j].key)) {
+				ret = info.callbacks[j].cb(
+					info.callbacks[j].key,
+					info.vec[i], info.callbacks[j].val);
+				if (ret < 0)
+					return ret;
+				break;
+			}
+	}
+
+	return 0;
+}
+
+void
+fips_test_write_one_case(void)
+{
+	uint32_t i;
+
+	for (i = 0; i < info.nb_vec_lines; i++)
+		fprintf(info.fp_wr, "%s\n", info.vec[i]);
+}
+
+static int
+parser_read_uint64_hex(uint64_t *value, const char *p)
+{
+	char *next;
+	uint64_t val;
+
+	p = skip_white_spaces(p);
+
+	val = strtoul(p, &next, 16);
+	if (p == next)
+		return -EINVAL;
+
+	p = skip_white_spaces(next);
+	if (*p != '\0')
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
+int
+parser_read_uint8_hex(uint8_t *value, const char *p)
+{
+	uint64_t val = 0;
+	int ret = parser_read_uint64_hex(&val, p);
+
+	if (ret < 0)
+		return ret;
+
+	if (val > UINT8_MAX)
+		return -ERANGE;
+
+	*value = val;
+	return 0;
+}
+
+int
+parse_uint8_known_len_hex_str(const char *key, char *src, struct fips_val *val)
+{
+	struct fips_val tmp_val = {0};
+	uint32_t len = val->len;
+	int ret;
+
+	if (len == 0) {
+		if (val->val != NULL) {
+			rte_free(val->val);
+			val->val = NULL;
+		}
+
+		return 0;
+	}
+
+	ret = parse_uint8_hex_str(key, src, &tmp_val);
+	if (ret < 0)
+		return ret;
+
+	if (tmp_val.len == val->len) {
+		val->val = tmp_val.val;
+		return 0;
+	}
+
+	if (tmp_val.len < val->len) {
+		rte_free(tmp_val.val);
+		return -EINVAL;
+	}
+
+	val->val = rte_zmalloc(NULL, val->len, 0);
+	if (!val->val) {
+		rte_free(tmp_val.val);
+		memset(val, 0, sizeof(*val));
+		return -ENOMEM;
+	}
+
+	memcpy(val->val, tmp_val.val, val->len);
+	rte_free(tmp_val.val);
+
+	return 0;
+}
+
+int
+parse_uint8_hex_str(const char *key, char *src, struct fips_val *val)
+{
+	uint32_t len, j;
+
+	src += strlen(key);
+
+	len = strlen(src) / 2;
+
+	if (val->val) {
+		rte_free(val->val);
+		val->val = NULL;
+	}
+
+	val->val = rte_zmalloc(NULL, len, 0);
+	if (!val->val)
+		return -ENOMEM;
+
+	for (j = 0; j < len; j++) {
+		char byte[3] = {src[j * 2], src[j * 2 + 1], '\0'};
+
+		if (parser_read_uint8_hex(&val->val[j], byte) < 0) {
+			rte_free(val->val);
+			memset(val, 0, sizeof(*val));
+			return -EINVAL;
+		}
+	}
+
+	val->len = len;
+
+	return 0;
+}
+
+int
+parser_read_uint32_val(const char *key, char *src, struct fips_val *val)
+{
+	char *data = src + strlen(key);
+	size_t data_len = strlen(data);
+	int ret;
+
+	if (data[data_len - 1] == ']') {
+		char *tmp_data = calloc(1, data_len + 1);
+
+		if (tmp_data == NULL)
+			return -ENOMEM;
+
+		strlcpy(tmp_data, data, data_len);
+
+		ret = parser_read_uint32(&val->len, tmp_data);
+
+		free(tmp_data);
+	} else
+		ret = parser_read_uint32(&val->len, data);
+
+	return ret;
+}
+
+int
+parser_read_uint32_bit_val(const char *key, char *src, struct fips_val *val)
+{
+	int ret;
+
+	ret = parser_read_uint32_val(key, src, val);
+
+	if (ret < 0)
+		return ret;
+
+	val->len /= 8;
+
+	return 0;
+}
+
+int
+writeback_hex_str(const char *key, char *dst, struct fips_val *val)
+{
+	char *str = dst;
+	uint32_t len;
+
+	str += strlen(key);
+
+	for (len = 0; len < val->len; len++)
+		snprintf(str + len * 2, 255, "%02x", val->val[len]);
+
+	return 0;
+}
+
+static int
+parser_read_uint64(uint64_t *value, const char *p)
+{
+	char *next;
+	uint64_t val;
+
+	p = skip_white_spaces(p);
+	if (!isdigit(*p))
+		return -EINVAL;
+
+	val = strtoul(p, &next, 10);
+	if (p == next)
+		return -EINVAL;
+
+	p = next;
+	switch (*p) {
+	case 'T':
+		val *= 1024ULL;
+		/* fall through */
+	case 'G':
+		val *= 1024ULL;
+		/* fall through */
+	case 'M':
+		val *= 1024ULL;
+		/* fall through */
+	case 'k':
+	case 'K':
+		val *= 1024ULL;
+		p++;
+		break;
+	}
+
+	p = skip_white_spaces(p);
+	if (*p != '\0')
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
+int
+parser_read_uint32(uint32_t *value, char *p)
+{
+	uint64_t val = 0;
+	int ret = parser_read_uint64(&val, p);
+
+	if (ret < 0)
+		return ret;
+
+	if (val > UINT32_MAX)
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
+void
+parse_write_hex_str(struct fips_val *src)
+{
+	writeback_hex_str("", info.one_line_text, src);
+
+	fprintf(info.fp_wr, "%s\n", info.one_line_text);
+}
+
+int
+update_info_vec(uint32_t count)
+{
+	const struct fips_test_callback *cb;
+	uint32_t i, j;
+
+	if (!info.writeback_callbacks)
+		return -1;
+
+	cb = &info.writeback_callbacks[0];
+
+	snprintf(info.vec[0], strlen(info.vec[0]) + 4, "%s%u", cb->key, count);
+
+	for (i = 1; i < info.nb_vec_lines; i++) {
+		for (j = 1; info.writeback_callbacks[j].key != NULL; j++) {
+			cb = &info.writeback_callbacks[j];
+			if (strstr(info.vec[i], cb->key)) {
+				cb->cb(cb->key, info.vec[i], cb->val);
+				break;
+			}
+		}
+	}
+
+	return 0;
+}
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
new file mode 100644
index 0000000..dd3bc09
--- /dev/null
+++ b/examples/fips_validation/fips_validation.h
@@ -0,0 +1,149 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _FIPS_VALIDATION_H_
+#define _FIPS_VALIDATION_H_
+
+#define FIPS_PARSE_ERR(fmt, args)					\
+	RTE_LOG(ERR, USER1, "FIPS parse error" ## fmt ## "\n", ## args)
+
+#define ERR_MSG_SIZE		128
+#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 MAX_STRING_SIZE		64
+
+#define POSITIVE_TEST		0
+#define NEGATIVE_TEST		-1
+
+#define REQ_FILE_PERFIX		"req"
+#define RSP_FILE_PERFIX		"rsp"
+#define FAX_FILE_PERFIX		"fax"
+
+enum fips_test_algorithms {
+		FIPS_TEST_ALGO_MAX
+};
+
+enum file_types {
+	FIPS_TYPE_REQ = 1,
+	FIPS_TYPE_FAX,
+	FIPS_TYPE_RSP
+};
+
+enum fips_test_op {
+	FIPS_TEST_ENC_AUTH_GEN = 1,
+	FIPS_TEST_DEC_AUTH_VERIF,
+};
+
+#define MAX_LINE_PER_VECTOR            16
+
+struct fips_val {
+	uint8_t *val;
+	uint32_t len;
+};
+
+struct fips_test_vector {
+	union {
+		struct {
+			struct fips_val key;
+			struct fips_val digest;
+			struct fips_val auth_aad;
+			struct fips_val aad;
+		} cipher_auth;
+		struct {
+			struct fips_val key;
+			struct fips_val digest;
+			struct fips_val aad;
+		} aead;
+	};
+
+	struct fips_val pt;
+	struct fips_val ct;
+	struct fips_val iv;
+
+	enum rte_crypto_op_status status;
+};
+
+typedef int (*post_prcess_t)(struct fips_val *val);
+
+typedef int (*parse_callback_t)(const char *key, char *text,
+		struct fips_val *val);
+
+struct fips_test_callback {
+	const char *key;
+	parse_callback_t cb;
+	struct fips_val *val;
+};
+
+struct fips_test_interim_info {
+	FILE *fp_rd;
+	FILE *fp_wr;
+	enum file_types file_type;
+	enum fips_test_algorithms algo;
+	char *one_line_text;
+	char *vec[MAX_LINE_PER_VECTOR];
+	uint32_t nb_vec_lines;
+	char device_name[MAX_STRING_SIZE];
+
+	enum fips_test_op op;
+
+	const struct fips_test_callback *callbacks;
+	const struct fips_test_callback *interim_callbacks;
+	const struct fips_test_callback *writeback_callbacks;
+
+	post_prcess_t parse_writeback;
+	post_prcess_t kat_check;
+};
+
+extern struct fips_test_vector vec;
+extern struct fips_test_interim_info info;
+
+int
+fips_test_init(const char *req_file_path, const char *rsp_file_path,
+		const char *device_name);
+
+void
+fips_test_clear(void);
+
+int
+fips_test_fetch_one_block(void);
+
+int
+fips_test_parse_one_case(void);
+
+void
+fips_test_write_one_case(void);
+
+int
+parser_read_uint8_hex(uint8_t *value, const char *p);
+
+int
+parse_uint8_hex_str(const char *key, char *src, struct fips_val *val);
+
+int
+parse_uint8_known_len_hex_str(const char *key, char *src, struct fips_val *val);
+
+int
+parser_read_uint32_val(const char *key, char *src, struct fips_val *val);
+
+int
+parser_read_uint32_bit_val(const char *key, char *src, struct fips_val *val);
+
+int
+parser_read_uint32(uint32_t *value, char *p);
+
+int
+parser_read_uint32_val(const char *key, char *src, struct fips_val *val);
+
+int
+writeback_hex_str(const char *key, char *dst, struct fips_val *val);
+
+void
+parse_write_hex_str(struct fips_val *src);
+
+int
+update_info_vec(uint32_t count);
+
+#endif
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
new file mode 100644
index 0000000..7083462
--- /dev/null
+++ b/examples/fips_validation/main.c
@@ -0,0 +1,388 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <sys/stat.h>
+#include <getopt.h>
+#include <dirent.h>
+
+#include <rte_cryptodev.h>
+#include <rte_cryptodev_pmd.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_string_fns.h>
+
+#include "fips_validation.h"
+
+#define REQ_FILE_PATH_KEYWORD	"req-file"
+#define RSP_FILE_PATH_KEYWORD	"rsp-file"
+#define FOLDER_KEYWORD		"path-is-folder"
+#define CRYPTODEV_KEYWORD	"cryptodev"
+#define CRYPTODEV_ID_KEYWORD	"cryptodev-id"
+
+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;
+	uint32_t dev_id;
+	struct rte_mempool *mpool;
+	struct rte_mempool *op_pool;
+	struct rte_mbuf *mbuf;
+	struct rte_crypto_op *op;
+	struct rte_cryptodev_sym_session *sess;
+} env;
+
+static int
+cryptodev_fips_validate_app_int(void)
+{
+	struct rte_cryptodev_config conf = {rte_socket_id(), 1};
+	struct rte_cryptodev_qp_conf qp_conf = {128};
+	int ret;
+
+	ret = rte_cryptodev_configure(env.dev_id, &conf);
+	if (ret < 0)
+		return ret;
+
+	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", 128, 0, 0,
+			UINT16_MAX, rte_socket_id());
+	if (!env.mpool)
+		return ret;
+
+	ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
+			rte_socket_id(), env.mpool);
+	if (ret < 0)
+		return ret;
+
+	ret = -ENOMEM;
+
+	env.op_pool = rte_crypto_op_pool_create(
+			"FIPS_OP_POOL",
+			RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+			1, 0,
+			16,
+			rte_socket_id());
+	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;
+
+	return 0;
+
+error_exit:
+	rte_mempool_free(env.mpool);
+	if (env.op_pool)
+		rte_mempool_free(env.op_pool);
+
+	return ret;
+}
+
+static void
+cryptodev_fips_validate_app_uninit(void)
+{
+	rte_pktmbuf_free(env.mbuf);
+	rte_crypto_op_free(env.op);
+	rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
+	rte_cryptodev_sym_session_free(env.sess);
+	rte_mempool_free(env.mpool);
+	rte_mempool_free(env.op_pool);
+}
+
+static int
+fips_test_one_file(void);
+
+static int
+parse_cryptodev_arg(char *arg)
+{
+	int id = rte_cryptodev_get_dev_id(arg);
+
+	if (id < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev name %s\n",
+				id, arg);
+		return id;
+	}
+
+	env.dev_id = (uint32_t)id;
+
+	return 0;
+}
+
+static int
+parse_cryptodev_id_arg(char *arg)
+{
+	uint32_t cryptodev_id;
+
+	if (parser_read_uint32(&cryptodev_id, arg) < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n",
+				-EINVAL, arg);
+		return -1;
+	}
+
+
+	if (!rte_cryptodev_pmd_is_valid_dev(cryptodev_id)) {
+		RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n",
+				cryptodev_id, arg);
+		return -1;
+	}
+
+	env.dev_id = (uint32_t)cryptodev_id;
+
+	return 0;
+}
+
+static void
+cryptodev_fips_validate_usage(const char *prgname)
+{
+	printf("%s [EAL options] --\n"
+		"  --%s: REQUEST-FILE-PATH\n"
+		"  --%s: RESPONSE-FILE-PATH\n"
+		"  --%s: indicating both paths are folders\n"
+		"  --%s: CRYPTODEV-NAME\n"
+		"  --%s: CRYPTODEV-ID-NAME\n",
+		prgname, REQ_FILE_PATH_KEYWORD, RSP_FILE_PATH_KEYWORD,
+		FOLDER_KEYWORD, CRYPTODEV_KEYWORD, CRYPTODEV_ID_KEYWORD);
+}
+
+static int
+cryptodev_fips_validate_parse_args(int argc, char **argv)
+{
+	int opt, ret;
+	char *prgname = argv[0];
+	char **argvopt;
+	int option_index;
+	struct option lgopts[] = {
+			{REQ_FILE_PATH_KEYWORD, required_argument, 0, 0},
+			{RSP_FILE_PATH_KEYWORD, required_argument, 0, 0},
+			{FOLDER_KEYWORD, no_argument, 0, 0},
+			{CRYPTODEV_KEYWORD, required_argument, 0, 0},
+			{CRYPTODEV_ID_KEYWORD, required_argument, 0, 0},
+			{NULL, 0, 0, 0}
+	};
+
+	argvopt = argv;
+
+	while ((opt = getopt_long(argc, argvopt, "s:",
+				  lgopts, &option_index)) != EOF) {
+
+		switch (opt) {
+		case 0:
+			if (strcmp(lgopts[option_index].name,
+					REQ_FILE_PATH_KEYWORD) == 0)
+				env.req_path = optarg;
+			else if (strcmp(lgopts[option_index].name,
+					RSP_FILE_PATH_KEYWORD) == 0)
+				env.rsp_path = optarg;
+			else if (strcmp(lgopts[option_index].name,
+					FOLDER_KEYWORD) == 0)
+				env.is_path_folder = 1;
+			else if (strcmp(lgopts[option_index].name,
+					CRYPTODEV_KEYWORD) == 0) {
+				ret = parse_cryptodev_arg(optarg);
+				if (ret < 0) {
+					cryptodev_fips_validate_usage(prgname);
+					return -EINVAL;
+				}
+			} else if (strcmp(lgopts[option_index].name,
+					CRYPTODEV_ID_KEYWORD) == 0) {
+				ret = parse_cryptodev_id_arg(optarg);
+				if (ret < 0) {
+					cryptodev_fips_validate_usage(prgname);
+					return -EINVAL;
+				}
+			} else {
+				cryptodev_fips_validate_usage(prgname);
+				return -EINVAL;
+			}
+			break;
+		default:
+			return -1;
+		}
+	}
+
+	if (env.req_path == NULL || env.rsp_path == NULL ||
+			env.dev_id == UINT32_MAX) {
+		cryptodev_fips_validate_usage(prgname);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+	int ret;
+
+	ret = rte_eal_init(argc, argv);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
+		return -1;
+	}
+
+	argc -= ret;
+	argv += ret;
+
+	ret = cryptodev_fips_validate_parse_args(argc, argv);
+	if (ret < 0)
+		rte_exit(EXIT_FAILURE, "Failed to parse arguments!\n");
+
+	ret = cryptodev_fips_validate_app_int();
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
+		return -1;
+	}
+
+	if (!env.is_path_folder) {
+		printf("Processing file %s... ", env.req_path);
+
+		ret = fips_test_init(env.req_path, env.rsp_path,
+			rte_cryptodev_name_get(env.dev_id));
+		if (ret < 0) {
+			RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
+					ret, env.req_path);
+			goto exit;
+		}
+
+
+		ret = fips_test_one_file();
+		if (ret < 0) {
+			RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
+					ret, env.req_path);
+			goto exit;
+		}
+
+		printf("Done\n");
+
+	} else {
+		struct dirent *dir;
+		DIR *d_req, *d_rsp;
+		char req_path[1024];
+		char rsp_path[1024];
+
+		d_req = opendir(env.req_path);
+		if (!d_req) {
+			RTE_LOG(ERR, USER1, "Error %i: Path %s not exist\n",
+					-EINVAL, env.req_path);
+			goto exit;
+		}
+
+		d_rsp = opendir(env.rsp_path);
+		if (!d_rsp) {
+			ret = mkdir(env.rsp_path, 0700);
+			if (ret == 0)
+				d_rsp = opendir(env.rsp_path);
+			else {
+				RTE_LOG(ERR, USER1, "Error %i: Invalid %s\n",
+						-EINVAL, env.rsp_path);
+				goto exit;
+			}
+		}
+		closedir(d_rsp);
+
+		while ((dir = readdir(d_req)) != NULL) {
+			if (strstr(dir->d_name, "req") == NULL)
+				continue;
+
+			snprintf(req_path, 1023, "%s/%s", env.req_path,
+					dir->d_name);
+			snprintf(rsp_path, 1023, "%s/%s", env.rsp_path,
+					dir->d_name);
+			strlcpy(strstr(rsp_path, "req"), "rsp", 4);
+
+			printf("Processing file %s... ", req_path);
+
+			ret = fips_test_init(req_path, rsp_path,
+			rte_cryptodev_name_get(env.dev_id));
+			if (ret < 0) {
+				RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
+						ret, req_path);
+				break;
+			}
+
+			ret = fips_test_one_file();
+			if (ret < 0) {
+				RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
+						ret, req_path);
+				break;
+			}
+
+			printf("Done\n");
+		}
+
+		closedir(d_req);
+	}
+
+
+exit:
+	fips_test_clear();
+	cryptodev_fips_validate_app_uninit();
+
+	return ret;
+
+}
+
+static void
+print_test_block(void)
+{
+	uint32_t i;
+
+	for (i = 0; i < info.nb_vec_lines; i++)
+		printf("%s\n", info.vec[i]);
+
+	printf("\n");
+}
+
+static int
+fips_test_one_file(void)
+{
+	int fetch_ret = 0, ret;
+
+	while (fetch_ret == 0) {
+		fetch_ret = fips_test_fetch_one_block();
+		if (fetch_ret < 0) {
+			RTE_LOG(ERR, USER1, "Error %i: Fetch block\n",
+					fetch_ret);
+			ret = fetch_ret;
+			goto error_one_case;
+		}
+
+		if (info.nb_vec_lines == 0) {
+			if (fetch_ret == -EOF)
+				break;
+
+			fprintf(info.fp_wr, "\n");
+			continue;
+		}
+
+		ret = fips_test_parse_one_case();
+		switch (ret) {
+		case 0:
+			if (ret == 0)
+				break;
+			RTE_LOG(ERR, USER1, "Error %i: test block\n",
+					ret);
+			goto error_one_case;
+		case 1:
+			break;
+		default:
+			RTE_LOG(ERR, USER1, "Error %i: Parse block\n",
+					ret);
+			goto error_one_case;
+		}
+
+		continue;
+error_one_case:
+		print_test_block();
+	}
+
+	fips_test_clear();
+
+}
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
new file mode 100644
index 0000000..cceed4f
--- /dev/null
+++ b/examples/fips_validation/meson.build
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Intel Corporation
+
+# meson file, for building this example as part of a main DPDK build.
+#
+# To build this example as a standalone application with an already-installed
+# DPDK instance, use 'make'
+
+deps += ['cryptodev']
+allow_experimental_apis = true
+sources = files(
+	'fips_validation.c',
+	'main.c'
+)
-- 
2.9.5

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

* [dpdk-dev] [PATCH v7 2/8] examples/fips_validation: support AES parsing
  2018-11-02  9:55     ` [dpdk-dev] [PATCH v7 " Kovacevic, Marko
  2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 1/8] examples/fips_validation: add cryptodev fips compliant application Kovacevic, Marko
@ 2018-11-02  9:55       ` Kovacevic, Marko
  2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 3/8] examples/fips_validation: support HMAC parsing Kovacevic, Marko
                         ` (6 subsequent siblings)
  8 siblings, 0 replies; 52+ messages in thread
From: Kovacevic, Marko @ 2018-11-02  9:55 UTC (permalink / raw)
  To: akhil.goyal; +Cc: dev, roy.fan.zhang, arkadiuszx.kusztal, Kovacevic, Marko

Added enablement for AES-CBC parser, to allow the
application to parser the aes request file and to validate all
test types supported.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 examples/fips_validation/Makefile              |   1 +
 examples/fips_validation/fips_validation.c     |   6 +
 examples/fips_validation/fips_validation.h     |  24 ++
 examples/fips_validation/fips_validation_aes.c | 186 +++++++++++++
 examples/fips_validation/main.c                | 346 ++++++++++++++++++++++++-
 examples/fips_validation/meson.build           |   1 +
 6 files changed, 563 insertions(+), 1 deletion(-)
 create mode 100644 examples/fips_validation/fips_validation_aes.c

diff --git a/examples/fips_validation/Makefile b/examples/fips_validation/Makefile
index 59d56c7..1eb1bc5 100644
--- a/examples/fips_validation/Makefile
+++ b/examples/fips_validation/Makefile
@@ -6,6 +6,7 @@ APP = fips_validation
 
 # all source are stored in SRCS-y
 SRCS-y := fips_validation.c
+SRCS-y += fips_validation_aes.c
 SRCS-y += main.c
 
 # Build using pkg-config variables if possible
diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index 58a3c1b..dba26d8 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -106,6 +106,12 @@ fips_test_parse_header(void)
 		return ret;
 
 	for (i = 0; i < info.nb_vec_lines; i++) {
+		if (strstr(info.vec[i], "AESVS")) {
+			info.algo = FIPS_TEST_ALGO_AES;
+			ret = parse_test_aes_init();
+			if (ret < 0)
+				return ret;
+		}
 
 		tmp = strstr(info.vec[i], "# Config info for ");
 		if (tmp != NULL) {
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index dd3bc09..e947de1 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -23,6 +23,7 @@
 #define FAX_FILE_PERFIX		"fax"
 
 enum fips_test_algorithms {
+		FIPS_TEST_ALGO_AES = 0,
 		FIPS_TEST_ALGO_MAX
 };
 
@@ -77,6 +78,21 @@ struct fips_test_callback {
 	struct fips_val *val;
 };
 
+enum fips_aesavs_test_types {
+	AESAVS_TYPE_GFXBOX = 1,
+	AESAVS_TYPE_KEYSBOX,
+	AESAVS_TYPE_VARKEY,
+	AESAVS_TYPE_VARTXT,
+	AESAVS_TYPE_MMT,
+	AESAVS_TYPE_MCT,
+};
+
+struct aesavs_interim_data {
+	enum fips_aesavs_test_types test_type;
+	uint32_t cipher_algo;
+	uint32_t key_len;
+};
+
 struct fips_test_interim_info {
 	FILE *fp_rd;
 	FILE *fp_wr;
@@ -87,6 +103,11 @@ struct fips_test_interim_info {
 	uint32_t nb_vec_lines;
 	char device_name[MAX_STRING_SIZE];
 
+	union {
+		struct aesavs_interim_data aes_data;
+
+	} interim_info;
+
 	enum fips_test_op op;
 
 	const struct fips_test_callback *callbacks;
@@ -117,6 +138,9 @@ void
 fips_test_write_one_case(void);
 
 int
+parse_test_aes_init(void);
+
+int
 parser_read_uint8_hex(uint8_t *value, const char *p);
 
 int
diff --git a/examples/fips_validation/fips_validation_aes.c b/examples/fips_validation/fips_validation_aes.c
new file mode 100644
index 0000000..f60b864
--- /dev/null
+++ b/examples/fips_validation/fips_validation_aes.c
@@ -0,0 +1,186 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+
+#include <rte_cryptodev.h>
+
+#include "fips_validation.h"
+
+#define MODE_STR	"AESVS"
+#define ALGO_STR	"test data for "
+#define OP_STR		"State"
+#define KEY_SIZE_STR	"Key Length : "
+
+
+#define COUNT_STR	"COUNT = "
+#define KEY_STR		"KEY = "
+#define IV_STR		"IV = "
+#define PT_STR		"PLAINTEXT = "
+#define CT_STR		"CIPHERTEXT = "
+
+#define OP_ENC_STR	"ENCRYPT"
+#define OP_DEC_STR	"DECRYPT"
+
+struct {
+	uint32_t type;
+	const char *desc;
+} aes_test_types[] = {
+		{AESAVS_TYPE_GFXBOX, "GFSbox"},
+		{AESAVS_TYPE_KEYSBOX, "KeySbox"},
+		{AESAVS_TYPE_VARKEY, "VarKey"},
+		{AESAVS_TYPE_VARTXT, "VarTxt"},
+		{AESAVS_TYPE_MMT, "MMT"},
+		{AESAVS_TYPE_MCT, "MCT"},
+};
+
+struct aes_test_algo {
+	const char *name;
+	enum rte_crypto_cipher_algorithm algo;
+} const algo_con[] = {
+		{"CBC", RTE_CRYPTO_CIPHER_AES_CBC},
+};
+
+static int
+parse_interim_enc_dec(const char *key,
+		__attribute__((__unused__)) char *text,
+		__attribute__((__unused__)) struct fips_val *val)
+{
+	if (strcmp(key, OP_ENC_STR) == 0)
+		info.op = FIPS_TEST_ENC_AUTH_GEN;
+	else if (strcmp(key, OP_DEC_STR) == 0)
+		info.op = FIPS_TEST_DEC_AUTH_VERIF;
+	else
+		return -1;
+
+	return 0;
+}
+
+struct fips_test_callback aes_tests_interim[] = {
+		{OP_ENC_STR, parse_interim_enc_dec, NULL},
+		{OP_DEC_STR, parse_interim_enc_dec, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback aes_tests_vectors[] = {
+		{KEY_STR, parse_uint8_hex_str, &vec.cipher_auth.key},
+		{IV_STR, parse_uint8_hex_str, &vec.iv},
+		{PT_STR, parse_uint8_hex_str, &vec.pt},
+		{CT_STR, parse_uint8_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback aes_tests_interim_vectors[] = {
+		{OP_ENC_STR, parse_interim_enc_dec, NULL},
+		{OP_DEC_STR, parse_interim_enc_dec, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback aes_writeback_callbacks[] = {
+		/** First element is used to pass COUNT string */
+		{COUNT_STR, NULL, NULL},
+		{IV_STR, writeback_hex_str, &vec.iv},
+		{KEY_STR, writeback_hex_str, &vec.cipher_auth.key},
+		{PT_STR, writeback_hex_str, &vec.pt},
+		{CT_STR, writeback_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+static int
+parse_test_aes_writeback(struct fips_val *val)
+{
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN)
+		fprintf(info.fp_wr, "%s", CT_STR);
+	else
+		fprintf(info.fp_wr, "%s", PT_STR);
+
+	parse_write_hex_str(val);
+
+	return 0;
+}
+
+static int
+rsp_test_aes_check(struct fips_val *val)
+{
+	struct fips_val *data;
+
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN)
+		data = &vec.ct;
+	else
+		data = &vec.pt;
+
+	if (memcmp(val->val, data->val, val->len) == 0)
+		fprintf(info.fp_wr, "Success\n");
+	else
+		fprintf(info.fp_wr, "Failed\n");
+
+	return 0;
+}
+
+int
+parse_test_aes_init(void)
+{
+	char *tmp;
+	uint32_t i, j;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		char *line = info.vec[i];
+
+		tmp = strstr(line, MODE_STR);
+		if (tmp) {
+			for (j = 0; j < RTE_DIM(aes_test_types); j++)
+				if (strstr(line, aes_test_types[j].desc)) {
+					info.interim_info.aes_data.test_type =
+							aes_test_types[j].type;
+					break;
+				}
+
+			if (j >= RTE_DIM(aes_test_types))
+				return -EINVAL;
+
+			tmp = strstr(line, ALGO_STR);
+			if (!tmp)
+				return -EINVAL;
+
+			tmp += strlen(ALGO_STR);
+			for (j = 0; j < RTE_DIM(algo_con); j++)
+				if (strcmp(algo_con[j].name, tmp) == 0) {
+					info.interim_info.aes_data.cipher_algo =
+						(uint32_t)algo_con[j].algo;
+					break;
+				}
+			if (j >= RTE_DIM(algo_con))
+				return -EINVAL;
+
+			continue;
+		}
+
+		tmp = strstr(line, OP_STR);
+		if (tmp)
+			continue;
+
+		tmp = strstr(line, KEY_SIZE_STR);
+		if (tmp) {
+			tmp += strlen(KEY_SIZE_STR);
+			if (parser_read_uint32
+					(&info.interim_info.aes_data.key_len,
+							tmp) < 0)
+				return -EINVAL;
+
+			info.interim_info.aes_data.key_len /= 8;
+
+			continue;
+		}
+	}
+
+	info.parse_writeback = parse_test_aes_writeback;
+	info.callbacks = aes_tests_vectors;
+	info.interim_callbacks = aes_tests_interim_vectors;
+	info.writeback_callbacks = aes_writeback_callbacks;
+	info.kat_check = rsp_test_aes_check;
+
+	return 0;
+}
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index 7083462..1f1ba99 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -329,6 +329,340 @@ 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;
+
+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);
+
+	__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;
+
+	memcpy(iv, vec.iv.val, 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);
+
+		if (!pt) {
+			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
+					-ENOMEM);
+			return -ENOMEM;
+		}
+
+		memcpy(pt, vec.pt.val, vec.pt.len);
+		sym->cipher.data.length = vec.pt.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;
+		}
+
+		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;
+		}
+
+		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);
+
+	return 0;
+}
+
+static int
+prepare_aes_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_cipher_xform *cipher_xform = &xform->cipher;
+
+	xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+
+	cipher_xform->algo = RTE_CRYPTO_CIPHER_AES_CBC;
+	cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_CIPHER_OP_ENCRYPT :
+			RTE_CRYPTO_CIPHER_OP_DECRYPT;
+	cipher_xform->key.data = vec.cipher_auth.key.val;
+	cipher_xform->key.length = vec.cipher_auth.key.len;
+	cipher_xform->iv.length = vec.iv.len;
+	cipher_xform->iv.offset = IV_OFF;
+
+	cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_AES_CBC;
+	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;
+	}
+
+	return 0;
+}
+
+static void
+get_writeback_data(struct fips_val *val)
+{
+	val->val = rte_pktmbuf_mtod(env.mbuf, uint8_t *);
+	val->len = rte_pktmbuf_pkt_len(env.mbuf);
+}
+
+static int
+fips_run_test(void)
+{
+	struct rte_crypto_sym_xform xform = {0};
+	uint16_t n_deqd;
+	int ret;
+
+	ret = test_ops.prepare_xform(&xform);
+	if (ret < 0)
+		return ret;
+
+	env.sess = rte_cryptodev_sym_session_create(env.mpool);
+	if (!env.sess)
+		return -ENOMEM;
+
+	ret = rte_cryptodev_sym_session_init(env.dev_id,
+			env.sess, &xform, env.mpool);
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: Init session\n",
+				ret);
+		return ret;
+	}
+
+	ret = test_ops.prepare_op();
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
+				ret);
+		return ret;
+	}
+
+	if (rte_cryptodev_enqueue_burst(env.dev_id, 0, &env.op, 1) < 1) {
+		RTE_LOG(ERR, USER1, "Error: Failed enqueue\n");
+		return ret;
+	}
+
+	do {
+		struct rte_crypto_op *deqd_op;
+
+		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
+				1);
+	} while (n_deqd == 0);
+
+	vec.status = env.op->status;
+
+	rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
+	rte_cryptodev_sym_session_free(env.sess);
+	env.sess = NULL;
+
+	return ret;
+}
+
+static int
+fips_generic_test(void)
+{
+	struct fips_val val;
+	int ret;
+
+	fips_test_write_one_case();
+
+	ret = fips_run_test();
+	if (ret < 0) {
+		if (ret == -EPERM) {
+			fprintf(info.fp_wr, "Bypass\n\n");
+			return 0;
+		}
+
+		return ret;
+	}
+
+	get_writeback_data(&val);
+
+	switch (info.file_type) {
+	case FIPS_TYPE_REQ:
+	case FIPS_TYPE_RSP:
+		if (info.parse_writeback == NULL)
+			return -EPERM;
+		ret = info.parse_writeback(&val);
+		if (ret < 0)
+			return ret;
+		break;
+	case FIPS_TYPE_FAX:
+		if (info.kat_check == NULL)
+			return -EPERM;
+		ret = info.kat_check(&val);
+		if (ret < 0)
+			return ret;
+		break;
+	}
+
+	fprintf(info.fp_wr, "\n");
+
+	return 0;
+}
+
+static int
+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;
+	uint8_t prev_out[AES_BLOCK_SIZE] = {0};
+	uint8_t prev_in[AES_BLOCK_SIZE] = {0};
+	uint32_t i, j, k;
+	int ret;
+
+	for (i = 0; i < AES_EXTERN_ITER; i++) {
+		if (i != 0)
+			update_info_vec(i);
+
+		fips_test_write_one_case();
+
+		for (j = 0; j < AES_INTERN_ITER; j++) {
+			ret = fips_run_test();
+			if (ret < 0) {
+				if (ret == -EPERM) {
+					fprintf(info.fp_wr, "Bypass\n");
+					return 0;
+				}
+
+				return ret;
+			}
+
+			get_writeback_data(&val);
+
+			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
+				memcpy(prev_in, vec.ct.val, AES_BLOCK_SIZE);
+
+			if (j == 0) {
+				memcpy(prev_out, val.val, AES_BLOCK_SIZE);
+
+				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+					memcpy(vec.pt.val, vec.iv.val,
+							AES_BLOCK_SIZE);
+					memcpy(vec.iv.val, val.val,
+							AES_BLOCK_SIZE);
+				} else {
+					memcpy(vec.ct.val, vec.iv.val,
+							AES_BLOCK_SIZE);
+					memcpy(vec.iv.val, prev_in,
+							AES_BLOCK_SIZE);
+				}
+				continue;
+			}
+
+			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+				memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
+				memcpy(vec.pt.val, prev_out, AES_BLOCK_SIZE);
+			} else {
+				memcpy(vec.iv.val, prev_in, AES_BLOCK_SIZE);
+				memcpy(vec.ct.val, prev_out, AES_BLOCK_SIZE);
+			}
+
+			if (j == AES_INTERN_ITER - 1)
+				continue;
+
+			memcpy(prev_out, val.val, AES_BLOCK_SIZE);
+		}
+
+		info.parse_writeback(&val);
+		fprintf(info.fp_wr, "\n");
+
+		if (i == AES_EXTERN_ITER - 1)
+			continue;
+
+		/** update key */
+		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
+		for (k = 0; k < vec.cipher_auth.key.len; k++) {
+			switch (vec.cipher_auth.key.len) {
+			case 16:
+				val_key.val[k] ^= val.val[k];
+				break;
+			case 24:
+				if (k < 8)
+					val_key.val[k] ^= prev_out[k + 8];
+				else
+					val_key.val[k] ^= val.val[k - 8];
+				break;
+			case 32:
+				if (k < 16)
+					val_key.val[k] ^= prev_out[k];
+				else
+					val_key.val[k] ^= val.val[k - 16];
+				break;
+			default:
+				return -1;
+			}
+		}
+
+		if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
+			memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
+	}
+
+	return 0;
+}
+
+static int
+init_test_ops(void)
+{
+	switch (info.algo) {
+	case FIPS_TEST_ALGO_AES:
+		test_ops.prepare_op = prepare_cipher_op;
+		test_ops.prepare_xform  = prepare_aes_xform;
+		if (info.interim_info.aes_data.test_type == AESAVS_TYPE_MCT)
+			test_ops.test = fips_mct_aes_test;
+		else
+			test_ops.test = fips_generic_test;
+		break;
+
+	default:
+		return -1;
+	}
+
+	return 0;
+}
+
 static void
 print_test_block(void)
 {
@@ -345,7 +679,14 @@ fips_test_one_file(void)
 {
 	int fetch_ret = 0, ret;
 
-	while (fetch_ret == 0) {
+
+	ret = init_test_ops();
+	if (ret < 0) {
+		RTE_LOG(ERR, USER1, "Error %i: Init test op\n", ret);
+		return ret;
+	}
+
+	while (ret >= 0 && fetch_ret == 0) {
 		fetch_ret = fips_test_fetch_one_block();
 		if (fetch_ret < 0) {
 			RTE_LOG(ERR, USER1, "Error %i: Fetch block\n",
@@ -365,6 +706,7 @@ fips_test_one_file(void)
 		ret = fips_test_parse_one_case();
 		switch (ret) {
 		case 0:
+			ret = test_ops.test();
 			if (ret == 0)
 				break;
 			RTE_LOG(ERR, USER1, "Error %i: test block\n",
@@ -385,4 +727,6 @@ fips_test_one_file(void)
 
 	fips_test_clear();
 
+	return ret;
+
 }
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
index cceed4f..fb20541 100644
--- a/examples/fips_validation/meson.build
+++ b/examples/fips_validation/meson.build
@@ -9,6 +9,7 @@
 deps += ['cryptodev']
 allow_experimental_apis = true
 sources = files(
+	'fips_validation_aes.c',
 	'fips_validation.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v7 3/8] examples/fips_validation: support HMAC parsing
  2018-11-02  9:55     ` [dpdk-dev] [PATCH v7 " Kovacevic, Marko
  2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 1/8] examples/fips_validation: add cryptodev fips compliant application Kovacevic, Marko
  2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 2/8] examples/fips_validation: support AES parsing Kovacevic, Marko
@ 2018-11-02  9:55       ` Kovacevic, Marko
  2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 4/8] examples/fips_validation: support TDES parsing Kovacevic, Marko
                         ` (5 subsequent siblings)
  8 siblings, 0 replies; 52+ messages in thread
From: Kovacevic, Marko @ 2018-11-02  9:55 UTC (permalink / raw)
  To: akhil.goyal; +Cc: dev, roy.fan.zhang, arkadiuszx.kusztal, Kovacevic, Marko

Added enablement for HMAC parser, to allow the
application to parser the hmac request files and to validate all
tests supported

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 examples/fips_validation/Makefile               |   1 +
 examples/fips_validation/fips_validation.c      |   5 ++
 examples/fips_validation/fips_validation.h      |   9 ++
 examples/fips_validation/fips_validation_hmac.c | 105 ++++++++++++++++++++++++
 examples/fips_validation/main.c                 | 103 +++++++++++++++++++++++
 examples/fips_validation/meson.build            |   1 +
 6 files changed, 224 insertions(+)
 create mode 100644 examples/fips_validation/fips_validation_hmac.c

diff --git a/examples/fips_validation/Makefile b/examples/fips_validation/Makefile
index 1eb1bc5..0d76101 100644
--- a/examples/fips_validation/Makefile
+++ b/examples/fips_validation/Makefile
@@ -7,6 +7,7 @@ APP = fips_validation
 # all source are stored in SRCS-y
 SRCS-y := fips_validation.c
 SRCS-y += fips_validation_aes.c
+SRCS-y += fips_validation_hmac.c
 SRCS-y += main.c
 
 # Build using pkg-config variables if possible
diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index dba26d8..24307b6 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -111,6 +111,11 @@ fips_test_parse_header(void)
 			ret = parse_test_aes_init();
 			if (ret < 0)
 				return ret;
+		} else if (strstr(info.vec[i], "HMAC")) {
+			info.algo = FIPS_TEST_ALGO_HMAC;
+			ret = parse_test_hmac_init();
+			if (ret < 0)
+				return ret;
 		}
 
 		tmp = strstr(info.vec[i], "# Config info for ");
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index e947de1..f9e3a3b 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -24,6 +24,7 @@
 
 enum fips_test_algorithms {
 		FIPS_TEST_ALGO_AES = 0,
+		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_MAX
 };
 
@@ -93,6 +94,10 @@ struct aesavs_interim_data {
 	uint32_t key_len;
 };
 
+struct hmac_interim_data {
+	enum rte_crypto_auth_algorithm algo;
+};
+
 struct fips_test_interim_info {
 	FILE *fp_rd;
 	FILE *fp_wr;
@@ -105,6 +110,7 @@ struct fips_test_interim_info {
 
 	union {
 		struct aesavs_interim_data aes_data;
+		struct hmac_interim_data hmac_data;
 
 	} interim_info;
 
@@ -141,6 +147,9 @@ int
 parse_test_aes_init(void);
 
 int
+parse_test_hmac_init(void);
+
+int
 parser_read_uint8_hex(uint8_t *value, const char *p);
 
 int
diff --git a/examples/fips_validation/fips_validation_hmac.c b/examples/fips_validation/fips_validation_hmac.c
new file mode 100644
index 0000000..97ac718
--- /dev/null
+++ b/examples/fips_validation/fips_validation_hmac.c
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+
+#include <rte_cryptodev.h>
+
+#include "fips_validation.h"
+
+#define ALGO_PREFIX	"[L="
+#define KEYLEN_STR	"Klen = "
+#define TAGLEN_STR	"Tlen = "
+
+#define COUNT_STR	"Count = "
+#define KEY_STR		"Key = "
+#define PT_STR		"Msg = "
+#define TAG_STR		"Mac = "
+
+struct hash_size_conversion {
+	const char *str;
+	enum rte_crypto_auth_algorithm algo;
+} hsc[] = {
+		{"20", RTE_CRYPTO_AUTH_SHA1_HMAC},
+		{"28", RTE_CRYPTO_AUTH_SHA224_HMAC},
+		{"32", RTE_CRYPTO_AUTH_SHA256_HMAC},
+		{"48", RTE_CRYPTO_AUTH_SHA384_HMAC},
+		{"64", RTE_CRYPTO_AUTH_SHA512_HMAC},
+};
+
+static int
+parse_interim_algo(__attribute__((__unused__)) const char *key,
+		char *text,
+		__attribute__((__unused__)) struct fips_val *val)
+{
+
+	uint32_t i;
+
+	for (i = 0; i < RTE_DIM(hsc); i++) {
+		if (strstr(text, hsc[i].str)) {
+			info.interim_info.hmac_data.algo = hsc[i].algo;
+			break;
+		}
+	}
+
+	if (i == RTE_DIM(hsc))
+		return -1;
+
+	return 0;
+}
+
+struct fips_test_callback hmac_tests_vectors[] = {
+		{KEYLEN_STR, parser_read_uint32_val, &vec.cipher_auth.key},
+		{TAGLEN_STR, parser_read_uint32_val, &vec.cipher_auth.digest},
+		{KEY_STR, parse_uint8_hex_str, &vec.cipher_auth.key},
+		{PT_STR, parse_uint8_hex_str, &vec.pt},
+		{TAG_STR, parse_uint8_hex_str, &vec.cipher_auth.digest},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback hmac_tests_interim_vectors[] = {
+		{ALGO_PREFIX, parse_interim_algo, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+static int
+parse_test_hmac_writeback(struct fips_val *val)
+{
+	struct fips_val val_local;
+
+	fprintf(info.fp_wr, "%s", TAG_STR);
+
+	val_local.val = val->val + vec.pt.len;
+	val_local.len = vec.cipher_auth.digest.len;
+
+	parse_write_hex_str(&val_local);
+	return 0;
+}
+
+static int
+rsp_test_hmac_check(struct fips_val *val)
+{
+	if (memcmp(val->val + vec.pt.len, vec.cipher_auth.digest.val,
+			vec.cipher_auth.digest.len) == 0)
+		fprintf(info.fp_wr, "Success\n");
+	else
+		fprintf(info.fp_wr, "Failed\n");
+
+	return 0;
+}
+
+int
+parse_test_hmac_init(void)
+{
+	info.op = FIPS_TEST_ENC_AUTH_GEN;
+	info.parse_writeback = parse_test_hmac_writeback;
+	info.callbacks = hmac_tests_vectors;
+	info.interim_callbacks = hmac_tests_interim_vectors;
+	info.writeback_callbacks = NULL;
+	info.kat_check = rsp_test_hmac_check;
+
+	return 0;
+}
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index 1f1ba99..da31d6a 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -401,6 +401,67 @@ prepare_cipher_op(void)
 }
 
 static int
+prepare_auth_op(void)
+{
+	struct rte_crypto_sym_op *sym = env.op->sym;
+
+	__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;
+
+	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.cipher_auth.digest.len);
+
+		if (!pt) {
+			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
+					-ENOMEM);
+			return -ENOMEM;
+		}
+
+		memcpy(pt, vec.pt.val, vec.pt.len);
+		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);
+
+	} 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 + vec.cipher_auth.digest.len);
+
+		if (!ct) {
+			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
+					-ENOMEM);
+			return -ENOMEM;
+		}
+
+		memcpy(ct, vec.ct.val, vec.ct.len);
+		sym->auth.data.length = vec.ct.len;
+		sym->auth.digest.data = vec.cipher_auth.digest.val;
+		sym->auth.digest.phys_addr = rte_malloc_virt2iova(
+				sym->auth.digest.data);
+	}
+
+	rte_crypto_op_attach_sym_session(env.op, env.sess);
+}
+
+static int
 prepare_aes_xform(struct rte_crypto_sym_xform *xform)
 {
 	const struct rte_cryptodev_symmetric_capability *cap;
@@ -440,6 +501,43 @@ prepare_aes_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_hmac_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 = info.interim_info.hmac_data.algo;
+	auth_xform->op = RTE_CRYPTO_AUTH_OP_GENERATE;
+	auth_xform->digest_length = vec.cipher_auth.digest.len;
+	auth_xform->key.data = vec.cipher_auth.key.val;
+	auth_xform->key.length = vec.cipher_auth.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 void
 get_writeback_data(struct fips_val *val)
 {
@@ -655,6 +753,11 @@ init_test_ops(void)
 		else
 			test_ops.test = fips_generic_test;
 		break;
+	case FIPS_TEST_ALGO_HMAC:
+		test_ops.prepare_op = prepare_auth_op;
+		test_ops.prepare_xform = prepare_hmac_xform;
+		test_ops.test = fips_generic_test;
+		break;
 
 	default:
 		return -1;
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
index fb20541..57bcf81 100644
--- a/examples/fips_validation/meson.build
+++ b/examples/fips_validation/meson.build
@@ -11,5 +11,6 @@ allow_experimental_apis = true
 sources = files(
 	'fips_validation_aes.c',
 	'fips_validation.c',
+	'fips_validation_hmac.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v7 4/8] examples/fips_validation: support TDES parsing
  2018-11-02  9:55     ` [dpdk-dev] [PATCH v7 " Kovacevic, Marko
                         ` (2 preceding siblings ...)
  2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 3/8] examples/fips_validation: support HMAC parsing Kovacevic, Marko
@ 2018-11-02  9:55       ` Kovacevic, Marko
  2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 5/8] examples/fips_validation: support GCM parsing Kovacevic, Marko
                         ` (4 subsequent siblings)
  8 siblings, 0 replies; 52+ messages in thread
From: Kovacevic, Marko @ 2018-11-02  9:55 UTC (permalink / raw)
  To: akhil.goyal; +Cc: dev, roy.fan.zhang, arkadiuszx.kusztal, Kovacevic, Marko

Added enablement for TDES parser, to allow the
application to parser the TDES request files and to validate all
test types supported.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 examples/fips_validation/Makefile               |   1 +
 examples/fips_validation/fips_validation.c      |   5 +
 examples/fips_validation/fips_validation.h      |  21 ++
 examples/fips_validation/fips_validation_aes.c  |   2 +
 examples/fips_validation/fips_validation_tdes.c | 264 ++++++++++++++++++++++++
 examples/fips_validation/main.c                 | 175 ++++++++++++++++
 examples/fips_validation/meson.build            |   1 +
 7 files changed, 469 insertions(+)
 create mode 100644 examples/fips_validation/fips_validation_tdes.c

diff --git a/examples/fips_validation/Makefile b/examples/fips_validation/Makefile
index 0d76101..57cc778 100644
--- a/examples/fips_validation/Makefile
+++ b/examples/fips_validation/Makefile
@@ -8,6 +8,7 @@ APP = fips_validation
 SRCS-y := fips_validation.c
 SRCS-y += fips_validation_aes.c
 SRCS-y += fips_validation_hmac.c
+SRCS-y += fips_validation_tdes.c
 SRCS-y += main.c
 
 # Build using pkg-config variables if possible
diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index 24307b6..86f443d 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -116,6 +116,11 @@ fips_test_parse_header(void)
 			ret = parse_test_hmac_init();
 			if (ret < 0)
 				return ret;
+		} else if (strstr(info.vec[i], "TDES")) {
+			info.algo = FIPS_TEST_ALGO_TDES;
+			ret = parse_test_tdes_init();
+			if (ret < 0)
+				return 0;
 		}
 
 		tmp = strstr(info.vec[i], "# Config info for ");
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index f9e3a3b..69a2116 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -25,6 +25,7 @@
 enum fips_test_algorithms {
 		FIPS_TEST_ALGO_AES = 0,
 		FIPS_TEST_ALGO_HMAC,
+		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_MAX
 };
 
@@ -88,6 +89,17 @@ enum fips_aesavs_test_types {
 	AESAVS_TYPE_MCT,
 };
 
+enum fips_tdes_test_types {
+	TDES_INVERSE_PERMUTATION = 0,
+	TDES_PERMUTATION,
+	TDES_SUBSTITUTION_TABLE,
+	TDES_VARIABLE_KEY,
+	TDES_VARIABLE_TEXT,
+	TDES_KAT,
+	TDES_MCT, /* Monte Carlo (Modes) Test */
+	TDES_MMT /* Multi block Message Test */
+};
+
 struct aesavs_interim_data {
 	enum fips_aesavs_test_types test_type;
 	uint32_t cipher_algo;
@@ -98,6 +110,11 @@ struct hmac_interim_data {
 	enum rte_crypto_auth_algorithm algo;
 };
 
+struct tdes_interim_data {
+	enum fips_tdes_test_types test_type;
+	uint32_t nb_keys;
+};
+
 struct fips_test_interim_info {
 	FILE *fp_rd;
 	FILE *fp_wr;
@@ -111,6 +128,7 @@ struct fips_test_interim_info {
 	union {
 		struct aesavs_interim_data aes_data;
 		struct hmac_interim_data hmac_data;
+		struct tdes_interim_data tdes_data;
 
 	} interim_info;
 
@@ -147,6 +165,9 @@ int
 parse_test_aes_init(void);
 
 int
+parse_test_tdes_init(void);
+
+int
 parse_test_hmac_init(void);
 
 int
diff --git a/examples/fips_validation/fips_validation_aes.c b/examples/fips_validation/fips_validation_aes.c
index f60b864..8cbc158 100644
--- a/examples/fips_validation/fips_validation_aes.c
+++ b/examples/fips_validation/fips_validation_aes.c
@@ -33,6 +33,8 @@ struct {
 		{AESAVS_TYPE_KEYSBOX, "KeySbox"},
 		{AESAVS_TYPE_VARKEY, "VarKey"},
 		{AESAVS_TYPE_VARTXT, "VarTxt"},
+		{TDES_VARIABLE_TEXT, "VARIABLE PLAINTEXT/CIPHERTEXT"},
+		{TDES_VARIABLE_TEXT, "KAT"},
 		{AESAVS_TYPE_MMT, "MMT"},
 		{AESAVS_TYPE_MCT, "MCT"},
 };
diff --git a/examples/fips_validation/fips_validation_tdes.c b/examples/fips_validation/fips_validation_tdes.c
new file mode 100644
index 0000000..5064ff3
--- /dev/null
+++ b/examples/fips_validation/fips_validation_tdes.c
@@ -0,0 +1,264 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include <rte_malloc.h>
+#include <rte_cryptodev.h>
+
+#include "fips_validation.h"
+
+#define NEW_LINE_STR	"#"
+#define TEST_TYPE_KEY	" for CBC"
+#define TEST_CBCI_KEY	" for CBCI"
+
+#define ENC_STR		"[ENCRYPT]"
+#define DEC_STR		"[DECRYPT]"
+
+#define COUNT_STR	"COUNT = "
+#define KEY1_STR	"KEY1 = "
+#define KEY2_STR	"KEY2 = "
+#define KEY3_STR	"KEY3 = "
+
+#define KEYS_STR	"KEYs = "
+#define IV_STR		"IV = "
+#define PT_STR		"PLAINTEXT = "
+#define CT_STR		"CIPHERTEXT = "
+#define NK_STR		"NumKeys = "
+
+#define SET_STR		" = "
+
+#define PLAIN_TEXT	0
+#define CIPHER_TEXT	1
+#define KEY_TEXT	2
+#define IV_TEXT		3
+
+#define DEVICE_STR	"# Config Info for : "
+
+struct {
+	uint32_t type;
+	const char *desc;
+} test_types[] = {
+		{TDES_INVERSE_PERMUTATION, "INVERSE PERMUTATION"},
+		{TDES_PERMUTATION, "PERMUTATION OPERATION"},
+		{TDES_SUBSTITUTION_TABLE, "SUBSTITUTION TABLE"},
+		{TDES_VARIABLE_KEY, "VARIABLE KEY"},
+		{TDES_VARIABLE_TEXT, "VARIABLE PLAINTEXT/CIPHERTEXT"},
+		{TDES_VARIABLE_TEXT, "KAT"},
+		{TDES_MCT, "Monte Carlo (Modes) Test"},
+		{TDES_MMT, "Multi block Message Test"},
+};
+
+static int
+writeback_tdes_hex_str(const char *key, char *dst, struct fips_val *val);
+
+static int
+parse_tdes_uint8_hex_str(const char *key, char *src, struct fips_val *val);
+
+static int
+parse_tdes_interim(const char *key,
+		__attribute__((__unused__)) char *text,
+		struct fips_val *val);
+
+struct fips_test_callback tdes_tests_vectors[] = {
+		{KEYS_STR, parse_tdes_uint8_hex_str, &vec.cipher_auth.key},
+		{KEY1_STR, parse_tdes_uint8_hex_str, &vec.cipher_auth.key},
+		{KEY2_STR, parse_tdes_uint8_hex_str, &vec.cipher_auth.key},
+		{KEY3_STR, parse_tdes_uint8_hex_str, &vec.cipher_auth.key},
+		{IV_STR, parse_uint8_hex_str, &vec.iv},
+		{PT_STR, parse_uint8_hex_str, &vec.pt},
+		{CT_STR, parse_uint8_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback tdes_tests_interim_vectors[] = {
+		{ENC_STR, parse_tdes_interim, NULL},
+		{DEC_STR, parse_tdes_interim, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback tdes_writeback_callbacks[] = {
+		/** First element is used to pass COUNT string */
+		{COUNT_STR, NULL, NULL},
+		{IV_STR, writeback_hex_str, &vec.iv},
+		{KEY1_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
+		{KEY2_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
+		{KEY3_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
+		{KEYS_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
+		{PT_STR, writeback_hex_str, &vec.pt},
+		{CT_STR, writeback_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+static int
+parse_tdes_interim(const char *key,
+		__attribute__((__unused__)) char *text,
+		__attribute__((__unused__)) struct fips_val *val)
+{
+	if (strstr(key, ENC_STR))
+		info.op = FIPS_TEST_ENC_AUTH_GEN;
+	else if (strstr(key, DEC_STR))
+		info.op = FIPS_TEST_DEC_AUTH_VERIF;
+	else if (strstr(NK_STR, "NumKeys = 1"))
+		info.interim_info.tdes_data.nb_keys = 1;
+	else if (strstr(NK_STR, "NumKeys = 2"))
+		info.interim_info.tdes_data.nb_keys = 2;
+	else if (strstr(NK_STR, "NumKeys = 3"))
+		info.interim_info.tdes_data.nb_keys = 3;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int
+parse_tdes_uint8_hex_str(const char *key, char *src, struct fips_val *val)
+{
+	uint8_t tmp_key[24] = {0};
+	uint32_t len, i;
+
+	src += strlen(key);
+
+	len = strlen(src) / 2;
+
+	if (val->val) {
+		memcpy(tmp_key, val->val, val->len);
+		rte_free(val->val);
+	}
+
+	val->val = rte_zmalloc(NULL, 24, 0);
+	if (!val->val)
+		return -1;
+
+	memcpy(val->val, tmp_key, 24);
+
+	if (strstr(key, KEYS_STR)) {
+		for (i = 0; i < len; i++) {
+			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
+
+			if (parser_read_uint8_hex(&val->val[i], byte) < 0)
+				goto error_exit;
+		}
+
+		memcpy(val->val + 8, val->val, 8);
+		memcpy(val->val + 16, val->val, 8);
+
+	} else if (strstr(key, KEY1_STR)) {
+		for (i = 0; i < len; i++) {
+			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
+
+			if (parser_read_uint8_hex(&val->val[i], byte) < 0)
+				goto error_exit;
+		}
+
+		if (info.interim_info.tdes_data.nb_keys == 2)
+			memcpy(val->val + 16, val->val, 8);
+
+	} else if (strstr(key, KEY2_STR)) {
+		for (i = 0; i < len; i++) {
+			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
+
+			if (parser_read_uint8_hex(&val->val[i + 8], byte) < 0)
+				goto error_exit;
+		}
+
+	} else if (strstr(key, KEY3_STR)) {
+		for (i = 0; i < len; i++) {
+			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
+
+			if (parser_read_uint8_hex(&val->val[i + 16], byte) < 0)
+				goto error_exit;
+		}
+	} else
+		return -EINVAL;
+
+	val->len = 24;
+
+	return 0;
+
+error_exit:
+	rte_free(val->val);
+	memset(val, 0, sizeof(*val));
+	return -EINVAL;
+}
+
+static int
+parse_test_tdes_writeback(struct fips_val *val)
+{
+
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN)
+		fprintf(info.fp_wr, "%s", CT_STR);
+	else
+		fprintf(info.fp_wr, "%s", PT_STR);
+
+	parse_write_hex_str(val);
+
+	return 0;
+
+}
+
+static int
+writeback_tdes_hex_str(const char *key, char *dst, struct fips_val *val)
+{
+	struct fips_val tmp_val;
+
+	tmp_val.len = 8;
+
+	if (strstr(key, KEY1_STR))
+		tmp_val.val = val->val;
+	else if (strstr(key, KEY2_STR))
+		tmp_val.val = val->val + 8;
+	else if (strstr(key, KEY3_STR))
+		tmp_val.val = val->val + 16;
+
+	return writeback_hex_str(key, dst, &tmp_val);
+}
+
+static int
+rsp_test_tdes_check(struct fips_val *val)
+{
+	struct fips_val *data;
+
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN)
+		data = &vec.ct;
+	else
+		data = &vec.pt;
+
+	if (memcmp(val->val, data->val, val->len) == 0)
+		fprintf(info.fp_wr, "Success\n");
+	else
+		fprintf(info.fp_wr, "Failed\n");
+
+	return 0;
+}
+
+int
+parse_test_tdes_init(void)
+{
+	uint32_t i;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		char *line = info.vec[i];
+		uint32_t j;
+
+		if (strstr(line, TEST_CBCI_KEY))
+			return -EPERM;
+
+		for (j = 0; j < RTE_DIM(test_types); j++)
+			if (strstr(line, test_types[j].desc)) {
+				info.interim_info.tdes_data.test_type =
+						test_types[j].type;
+				break;
+			}
+	}
+
+	info.parse_writeback = parse_test_tdes_writeback;
+	info.callbacks = tdes_tests_vectors;
+	info.interim_callbacks = tdes_tests_interim_vectors;
+	info.writeback_callbacks = tdes_writeback_callbacks;
+	info.kat_check = rsp_test_tdes_check;
+
+	return 0;
+}
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index da31d6a..3880681 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -502,6 +502,46 @@ prepare_aes_xform(struct rte_crypto_sym_xform *xform)
 }
 
 static int
+prepare_tdes_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_cipher_xform *cipher_xform = &xform->cipher;
+
+	xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+
+	cipher_xform->algo = RTE_CRYPTO_CIPHER_3DES_CBC;
+	cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_CIPHER_OP_ENCRYPT :
+			RTE_CRYPTO_CIPHER_OP_DECRYPT;
+	cipher_xform->key.data = vec.cipher_auth.key.val;
+	cipher_xform->key.length = vec.cipher_auth.key.len;
+	cipher_xform->iv.length = vec.iv.len;
+	cipher_xform->iv.offset = IV_OFF;
+
+	cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_3DES_CBC;
+	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;
+	}
+
+	return 0;
+}
+
+static int
 prepare_hmac_xform(struct rte_crypto_sym_xform *xform)
 {
 	const struct rte_cryptodev_symmetric_capability *cap;
@@ -640,6 +680,133 @@ fips_generic_test(void)
 }
 
 static int
+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;
+	uint8_t prev_out[TDES_BLOCK_SIZE];
+	uint8_t prev_prev_out[TDES_BLOCK_SIZE];
+	uint8_t prev_in[TDES_BLOCK_SIZE];
+	uint32_t i, j, k;
+	int ret;
+
+	for (i = 0; i < TDES_EXTERN_ITER; i++) {
+		if (i != 0)
+			update_info_vec(i);
+
+		fips_test_write_one_case();
+
+		for (j = 0; j < TDES_INTERN_ITER; j++) {
+			ret = fips_run_test();
+			if (ret < 0) {
+				if (ret == -EPERM) {
+					fprintf(info.fp_wr, "Bypass\n");
+					return 0;
+				}
+
+				return ret;
+			}
+
+			get_writeback_data(&val);
+
+			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
+				memcpy(prev_in, vec.ct.val, TDES_BLOCK_SIZE);
+
+			if (j == 0) {
+				memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
+
+				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+					memcpy(vec.pt.val, vec.iv.val,
+							TDES_BLOCK_SIZE);
+					memcpy(vec.iv.val, val.val,
+							TDES_BLOCK_SIZE);
+				} else {
+					memcpy(vec.iv.val, vec.ct.val,
+							TDES_BLOCK_SIZE);
+					memcpy(vec.ct.val, val.val,
+							TDES_BLOCK_SIZE);
+				}
+				continue;
+			}
+
+			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+				memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
+				memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
+			} else {
+				memcpy(vec.iv.val, vec.ct.val, TDES_BLOCK_SIZE);
+				memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
+			}
+
+			if (j == TDES_INTERN_ITER - 1)
+				continue;
+
+			memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
+
+			if (j == TDES_INTERN_ITER - 3)
+				memcpy(prev_prev_out, val.val, TDES_BLOCK_SIZE);
+		}
+
+		info.parse_writeback(&val);
+		fprintf(info.fp_wr, "\n");
+
+		if (i == TDES_EXTERN_ITER - 1)
+			continue;
+
+		/** update key */
+		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
+
+		if (info.interim_info.tdes_data.nb_keys == 0) {
+			if (memcmp(val_key.val, val_key.val + 8, 8) == 0)
+				info.interim_info.tdes_data.nb_keys = 1;
+			else if (memcmp(val_key.val, val_key.val + 16, 8) == 0)
+				info.interim_info.tdes_data.nb_keys = 2;
+			else
+				info.interim_info.tdes_data.nb_keys = 3;
+
+		}
+
+		for (k = 0; k < TDES_BLOCK_SIZE; k++) {
+
+			switch (info.interim_info.tdes_data.nb_keys) {
+			case 3:
+				val_key.val[k] ^= val.val[k];
+				val_key.val[k + 8] ^= prev_out[k];
+				val_key.val[k + 16] ^= prev_prev_out[k];
+				break;
+			case 2:
+				val_key.val[k] ^= val.val[k];
+				val_key.val[k + 8] ^= prev_out[k];
+				val_key.val[k + 16] ^= val.val[k];
+				break;
+			default: /* case 1 */
+				val_key.val[k] ^= val.val[k];
+				val_key.val[k + 8] ^= val.val[k];
+				val_key.val[k + 16] ^= val.val[k];
+				break;
+			}
+
+		}
+
+		for (k = 0; k < 24; k++)
+			val_key.val[k] = (__builtin_popcount(val_key.val[k]) &
+					0x1) ?
+					val_key.val[k] : (val_key.val[k] ^ 0x1);
+
+		if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+			memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
+			memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
+		} else {
+			memcpy(vec.iv.val, prev_out, TDES_BLOCK_SIZE);
+			memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
+		}
+	}
+
+	return 0;
+}
+
+static int
 fips_mct_aes_test(void)
 {
 #define AES_BLOCK_SIZE	16
@@ -758,6 +925,14 @@ init_test_ops(void)
 		test_ops.prepare_xform = prepare_hmac_xform;
 		test_ops.test = fips_generic_test;
 		break;
+	case FIPS_TEST_ALGO_TDES:
+		test_ops.prepare_op = prepare_cipher_op;
+		test_ops.prepare_xform  = prepare_tdes_xform;
+		if (info.interim_info.tdes_data.test_type == TDES_MCT)
+			test_ops.test = fips_mct_tdes_test;
+		else
+			test_ops.test = fips_generic_test;
+		break;
 
 	default:
 		return -1;
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
index 57bcf81..781ad5f 100644
--- a/examples/fips_validation/meson.build
+++ b/examples/fips_validation/meson.build
@@ -12,5 +12,6 @@ sources = files(
 	'fips_validation_aes.c',
 	'fips_validation.c',
 	'fips_validation_hmac.c',
+	'fips_validation_tdes.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v7 5/8] examples/fips_validation: support GCM parsing
  2018-11-02  9:55     ` [dpdk-dev] [PATCH v7 " Kovacevic, Marko
                         ` (3 preceding siblings ...)
  2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 4/8] examples/fips_validation: support TDES parsing Kovacevic, Marko
@ 2018-11-02  9:55       ` Kovacevic, Marko
  2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 6/8] examples/fips_validation: support CMAC parsing Kovacevic, Marko
                         ` (3 subsequent siblings)
  8 siblings, 0 replies; 52+ messages in thread
From: Kovacevic, Marko @ 2018-11-02  9:55 UTC (permalink / raw)
  To: akhil.goyal; +Cc: dev, roy.fan.zhang, arkadiuszx.kusztal, Kovacevic, Marko

Added enablement for GCM parser, to allow the
application to parser the GCM request file and to validate all
tests supported.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 examples/fips_validation/Makefile              |   1 +
 examples/fips_validation/fips_validation.c     |   5 +
 examples/fips_validation/fips_validation.h     |   4 +
 examples/fips_validation/fips_validation_gcm.c | 125 +++++++++++++++++++++++++
 examples/fips_validation/main.c                | 116 ++++++++++++++++++++++-
 examples/fips_validation/meson.build           |   1 +
 6 files changed, 251 insertions(+), 1 deletion(-)
 create mode 100644 examples/fips_validation/fips_validation_gcm.c

diff --git a/examples/fips_validation/Makefile b/examples/fips_validation/Makefile
index 57cc778..6373ac3 100644
--- a/examples/fips_validation/Makefile
+++ b/examples/fips_validation/Makefile
@@ -9,6 +9,7 @@ SRCS-y := fips_validation.c
 SRCS-y += fips_validation_aes.c
 SRCS-y += fips_validation_hmac.c
 SRCS-y += fips_validation_tdes.c
+SRCS-y += fips_validation_gcm.c
 SRCS-y += main.c
 
 # Build using pkg-config variables if possible
diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index 86f443d..1b926b8 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -111,6 +111,11 @@ fips_test_parse_header(void)
 			ret = parse_test_aes_init();
 			if (ret < 0)
 				return ret;
+		} else if (strstr(info.vec[i], "GCM")) {
+			info.algo = FIPS_TEST_ALGO_AES_GCM;
+			ret = parse_test_gcm_init();
+			if (ret < 0)
+				return ret;
 		} else if (strstr(info.vec[i], "HMAC")) {
 			info.algo = FIPS_TEST_ALGO_HMAC;
 			ret = parse_test_hmac_init();
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index 69a2116..4cceff5 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -24,6 +24,7 @@
 
 enum fips_test_algorithms {
 		FIPS_TEST_ALGO_AES = 0,
+		FIPS_TEST_ALGO_AES_GCM,
 		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_MAX
@@ -171,6 +172,9 @@ int
 parse_test_hmac_init(void);
 
 int
+parse_test_gcm_init(void);
+
+int
 parser_read_uint8_hex(uint8_t *value, const char *p);
 
 int
diff --git a/examples/fips_validation/fips_validation_gcm.c b/examples/fips_validation/fips_validation_gcm.c
new file mode 100644
index 0000000..0509b10
--- /dev/null
+++ b/examples/fips_validation/fips_validation_gcm.c
@@ -0,0 +1,125 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+
+#include <rte_cryptodev.h>
+
+#include "fips_validation.h"
+
+#define NEW_LINE_STR	"#"
+#define OP_STR		"GCM "
+
+#define PARAM_PREFIX	"["
+#define KEYLEN_STR	"Keylen = "
+#define IVLEN_STR	"IVlen = "
+#define PTLEN_STR	"PTlen = "
+#define AADLEN_STR	"AADlen = "
+#define TAGLEN_STR	"Taglen = "
+
+#define COUNT_STR	"Count = "
+#define KEY_STR		"Key = "
+#define IV_STR		"IV = "
+#define PT_STR		"PT = "
+#define CT_STR		"CT = "
+#define TAG_STR		"Tag = "
+#define AAD_STR		"AAD = "
+
+#define OP_ENC_STR	"Encrypt"
+#define OP_DEC_STR	"Decrypt"
+
+#define NEG_TEST_STR	"FAIL"
+
+struct fips_test_callback gcm_dec_vectors[] = {
+		{KEY_STR, parse_uint8_known_len_hex_str, &vec.cipher_auth.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.cipher_auth.aad},
+		{TAG_STR, parse_uint8_known_len_hex_str,
+				&vec.cipher_auth.digest},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+struct fips_test_callback gcm_interim_vectors[] = {
+		{KEYLEN_STR, parser_read_uint32_bit_val, &vec.cipher_auth.key},
+		{IVLEN_STR, parser_read_uint32_bit_val, &vec.iv},
+		{PTLEN_STR, parser_read_uint32_bit_val, &vec.pt},
+		{AADLEN_STR, parser_read_uint32_bit_val, &vec.cipher_auth.aad},
+		{TAGLEN_STR, parser_read_uint32_bit_val,
+				&vec.cipher_auth.digest},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback gcm_enc_vectors[] = {
+		{KEY_STR, parse_uint8_known_len_hex_str, &vec.cipher_auth.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.cipher_auth.aad},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+static int
+parse_test_gcm_writeback(struct fips_val *val)
+{
+	struct fips_val tmp_val;
+
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+		fprintf(info.fp_wr, "%s", CT_STR);
+
+		tmp_val.val = val->val;
+		tmp_val.len = vec.pt.len;
+
+		parse_write_hex_str(&tmp_val);
+
+		fprintf(info.fp_wr, "%s", TAG_STR);
+
+		tmp_val.val = val->val + vec.pt.len;
+		tmp_val.len = val->len - vec.pt.len;
+
+		parse_write_hex_str(&tmp_val);
+	} else {
+		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS) {
+			fprintf(info.fp_wr, "%s", PT_STR);
+
+			tmp_val.val = val->val;
+			tmp_val.len = vec.pt.len;
+
+			parse_write_hex_str(&tmp_val);
+		} else
+			fprintf(info.fp_wr, "%s\n", NEG_TEST_STR);
+	}
+
+	return 0;
+}
+
+int
+parse_test_gcm_init(void)
+{
+	char *tmp;
+	uint32_t i;
+
+
+	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;
+			} else if (strstr(line, OP_DEC_STR)) {
+				info.op = FIPS_TEST_DEC_AUTH_VERIF;
+				info.callbacks = gcm_dec_vectors;
+			} else
+				return -EINVAL;
+		}
+	}
+
+	info.interim_callbacks = gcm_interim_vectors;
+	info.parse_writeback = parse_test_gcm_writeback;
+
+	return 0;
+}
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index 3880681..c693e87 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -462,6 +462,70 @@ prepare_auth_op(void)
 }
 
 static int
+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);
+
+	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+	rte_pktmbuf_reset(env.mbuf);
+
+	memcpy(iv, vec.iv.val, vec.iv.len);
+
+	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 (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);
+
+		if (!pt) {
+			RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n",
+					-ENOMEM);
+			return -ENOMEM;
+		}
+
+		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);
+	} 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;
+		}
+
+		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);
+	}
+
+	rte_crypto_op_attach_sym_session(env.op, env.sess);
+}
+
+static int
 prepare_aes_xform(struct rte_crypto_sym_xform *xform)
 {
 	const struct rte_cryptodev_symmetric_capability *cap;
@@ -578,6 +642,52 @@ prepare_hmac_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_gcm_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_aead_xform *aead_xform = &xform->aead;
+
+	xform->type = RTE_CRYPTO_SYM_XFORM_AEAD;
+
+	aead_xform->algo = RTE_CRYPTO_AEAD_AES_GCM;
+	aead_xform->aad_length = vec.aead.aad.len;
+	aead_xform->digest_length = vec.aead.digest.len;
+	aead_xform->iv.offset = IV_OFF;
+	aead_xform->iv.length = vec.iv.len;
+	aead_xform->key.data = vec.aead.key.val;
+	aead_xform->key.length = vec.aead.key.len;
+	aead_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_AEAD_OP_ENCRYPT :
+			RTE_CRYPTO_AEAD_OP_DECRYPT;
+
+	cap_idx.algo.aead = aead_xform->algo;
+	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
+
+	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_aead(cap,
+			aead_xform->key.length,
+			aead_xform->digest_length, aead_xform->aad_length,
+			aead_xform->iv.length) != 0) {
+		RTE_LOG(ERR, USER1,
+			"PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n",
+				info.device_name, aead_xform->key.length,
+				aead_xform->digest_length,
+				aead_xform->aad_length,
+				aead_xform->iv.length);
+		return -EPERM;
+	}
+
+	return 0;
+}
+
 static void
 get_writeback_data(struct fips_val *val)
 {
@@ -933,7 +1043,11 @@ init_test_ops(void)
 		else
 			test_ops.test = fips_generic_test;
 		break;
-
+	case FIPS_TEST_ALGO_AES_GCM:
+		test_ops.prepare_op = prepare_aead_op;
+		test_ops.prepare_xform = prepare_gcm_xform;
+		test_ops.test = fips_generic_test;
+		break;
 	default:
 		return -1;
 	}
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
index 781ad5f..0cc8bc4 100644
--- a/examples/fips_validation/meson.build
+++ b/examples/fips_validation/meson.build
@@ -13,5 +13,6 @@ sources = files(
 	'fips_validation.c',
 	'fips_validation_hmac.c',
 	'fips_validation_tdes.c',
+	'fips_validation_gcm.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v7 6/8] examples/fips_validation: support CMAC parsing
  2018-11-02  9:55     ` [dpdk-dev] [PATCH v7 " Kovacevic, Marko
                         ` (4 preceding siblings ...)
  2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 5/8] examples/fips_validation: support GCM parsing Kovacevic, Marko
@ 2018-11-02  9:55       ` Kovacevic, Marko
  2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 7/8] examples/fips_validation: support CCM parsing Kovacevic, Marko
                         ` (2 subsequent siblings)
  8 siblings, 0 replies; 52+ messages in thread
From: Kovacevic, Marko @ 2018-11-02  9:55 UTC (permalink / raw)
  To: akhil.goyal; +Cc: dev, roy.fan.zhang, arkadiuszx.kusztal, Kovacevic, Marko

Added enablement for CMAC parser, to allow the
application to parser the cmac request files and to validate all
test types supported.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 examples/fips_validation/Makefile               |   1 +
 examples/fips_validation/fips_validation.c      |   5 +
 examples/fips_validation/fips_validation.h      |   4 +
 examples/fips_validation/fips_validation_cmac.c | 116 ++++++++++++++++++++++++
 examples/fips_validation/main.c                 |  43 +++++++++
 examples/fips_validation/meson.build            |   1 +
 6 files changed, 170 insertions(+)
 create mode 100644 examples/fips_validation/fips_validation_cmac.c

diff --git a/examples/fips_validation/Makefile b/examples/fips_validation/Makefile
index 6373ac3..77b15ae 100644
--- a/examples/fips_validation/Makefile
+++ b/examples/fips_validation/Makefile
@@ -10,6 +10,7 @@ SRCS-y += fips_validation_aes.c
 SRCS-y += fips_validation_hmac.c
 SRCS-y += fips_validation_tdes.c
 SRCS-y += fips_validation_gcm.c
+SRCS-y += fips_validation_cmac.c
 SRCS-y += main.c
 
 # Build using pkg-config variables if possible
diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index 1b926b8..fdf6f64 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -116,6 +116,11 @@ fips_test_parse_header(void)
 			ret = parse_test_gcm_init();
 			if (ret < 0)
 				return ret;
+		} else if (strstr(info.vec[i], "CMAC")) {
+			info.algo = FIPS_TEST_ALGO_AES_CMAC;
+			ret = parse_test_cmac_init();
+			if (ret < 0)
+				return 0;
 		} else if (strstr(info.vec[i], "HMAC")) {
 			info.algo = FIPS_TEST_ALGO_HMAC;
 			ret = parse_test_hmac_init();
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index 4cceff5..8dffe8e 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -25,6 +25,7 @@
 enum fips_test_algorithms {
 		FIPS_TEST_ALGO_AES = 0,
 		FIPS_TEST_ALGO_AES_GCM,
+		FIPS_TEST_ALGO_AES_CMAC,
 		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_MAX
@@ -175,6 +176,9 @@ int
 parse_test_gcm_init(void);
 
 int
+parse_test_cmac_init(void);
+
+int
 parser_read_uint8_hex(uint8_t *value, const char *p);
 
 int
diff --git a/examples/fips_validation/fips_validation_cmac.c b/examples/fips_validation/fips_validation_cmac.c
new file mode 100644
index 0000000..54c951e
--- /dev/null
+++ b/examples/fips_validation/fips_validation_cmac.c
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+#include <rte_string_fns.h>
+
+#include <rte_cryptodev.h>
+
+#include "fips_validation.h"
+
+#define NEW_LINE_STR	"#"
+#define OP_STR		"CMAC"
+
+#define ALGO_STR	"Alg = "
+#define MODE_STR	"Mode = "
+
+#define COUNT_STR	"Count = "
+#define KLEN_STR	"Klen = "
+#define PTLEN_STR	"Mlen = "
+#define TAGLEN_STR	"Tlen = "
+#define KEY_STR		"Key = "
+#define PT_STR		"Msg = "
+#define TAG_STR		"Mac = "
+
+#define GEN_STR		"Generate"
+#define VERIF_STR	"Verify"
+
+#define POS_NEG_STR	"Result = "
+#define PASS_STR	"P"
+#define FAIL_STR	"F"
+
+struct hash_algo_conversion {
+	const char *str;
+	enum fips_test_algorithms algo;
+} cmac_algo[] = {
+		{"AES", FIPS_TEST_ALGO_AES_CMAC},
+};
+
+static int
+parse_test_cmac_writeback(struct fips_val *val)
+{
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+		struct fips_val tmp_val = {val->val + vec.pt.len,
+				vec.cipher_auth.digest.len};
+
+		fprintf(info.fp_wr, "%s", TAG_STR);
+		parse_write_hex_str(&tmp_val);
+	} else {
+		fprintf(info.fp_wr, "%s", POS_NEG_STR);
+
+		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS)
+			fprintf(info.fp_wr, "%s\n", PASS_STR);
+		else if (vec.status == RTE_CRYPTO_OP_STATUS_AUTH_FAILED)
+			fprintf(info.fp_wr, "%s\n", FAIL_STR);
+		else
+			fprintf(info.fp_wr, "Error\n");
+	}
+
+	return 0;
+}
+
+struct fips_test_callback cmac_tests_vectors[] = {
+		{KLEN_STR, parser_read_uint32_val, &vec.cipher_auth.key},
+		{PTLEN_STR, parser_read_uint32_val, &vec.pt},
+		{TAGLEN_STR, parser_read_uint32_val, &vec.cipher_auth.digest},
+		{KEY_STR, parse_uint8_hex_str, &vec.cipher_auth.key},
+		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
+		{TAG_STR, parse_uint8_known_len_hex_str,
+				&vec.cipher_auth.digest},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+int
+parse_test_cmac_init(void)
+{
+	char *tmp;
+	uint32_t i, j;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		char *line = info.vec[i];
+
+		tmp = strstr(line, ALGO_STR);
+		if (!tmp)
+			continue;
+
+		for (j = 0; j < RTE_DIM(cmac_algo); j++) {
+			if (!strstr(line, cmac_algo[j].str))
+				continue;
+
+			info.algo = cmac_algo[j].algo;
+			break;
+		}
+
+		if (j == RTE_DIM(cmac_algo))
+			return -EINVAL;
+
+		tmp = strstr(line, MODE_STR);
+		if (!tmp)
+			return -1;
+
+		if (strstr(tmp, GEN_STR))
+			info.op = FIPS_TEST_ENC_AUTH_GEN;
+		else if (strstr(tmp, VERIF_STR))
+			info.op = FIPS_TEST_DEC_AUTH_VERIF;
+		else
+			return -EINVAL;
+	}
+
+	info.parse_writeback = parse_test_cmac_writeback;
+	info.callbacks = cmac_tests_vectors;
+
+	return 0;
+}
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index c693e87..e953f3e 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -688,6 +688,44 @@ prepare_gcm_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_cmac_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_CMAC;
+	auth_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_AUTH_OP_GENERATE : RTE_CRYPTO_AUTH_OP_VERIFY;
+	auth_xform->digest_length = vec.cipher_auth.digest.len;
+	auth_xform->key.data = vec.cipher_auth.key.val;
+	auth_xform->key.length = vec.cipher_auth.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 void
 get_writeback_data(struct fips_val *val)
 {
@@ -1048,6 +1086,11 @@ init_test_ops(void)
 		test_ops.prepare_xform = prepare_gcm_xform;
 		test_ops.test = fips_generic_test;
 		break;
+	case FIPS_TEST_ALGO_AES_CMAC:
+		test_ops.prepare_op = prepare_auth_op;
+		test_ops.prepare_xform = prepare_cmac_xform;
+		test_ops.test = fips_generic_test;
+		break;
 	default:
 		return -1;
 	}
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
index 0cc8bc4..a0d38fa 100644
--- a/examples/fips_validation/meson.build
+++ b/examples/fips_validation/meson.build
@@ -14,5 +14,6 @@ sources = files(
 	'fips_validation_hmac.c',
 	'fips_validation_tdes.c',
 	'fips_validation_gcm.c',
+	'fips_validation_cmac.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v7 7/8] examples/fips_validation: support CCM parsing
  2018-11-02  9:55     ` [dpdk-dev] [PATCH v7 " Kovacevic, Marko
                         ` (5 preceding siblings ...)
  2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 6/8] examples/fips_validation: support CMAC parsing Kovacevic, Marko
@ 2018-11-02  9:55       ` Kovacevic, Marko
  2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 8/8] doc: add fips validation application guide Kovacevic, Marko
  2018-11-02 11:23       ` [dpdk-dev] [PATCH v7 0/8] FIPS validation capability Akhil Goyal
  8 siblings, 0 replies; 52+ messages in thread
From: Kovacevic, Marko @ 2018-11-02  9:55 UTC (permalink / raw)
  To: akhil.goyal; +Cc: dev, roy.fan.zhang, arkadiuszx.kusztal, Kovacevic, Marko

Added enablement for CCM parser, to allow the
application to parser the ccm request files and to validate all
test types supported.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 examples/fips_validation/Makefile              |   1 +
 examples/fips_validation/fips_validation.c     |   5 +
 examples/fips_validation/fips_validation.h     |  22 ++
 examples/fips_validation/fips_validation_ccm.c | 272 +++++++++++++++++++++++++
 examples/fips_validation/main.c                |  56 ++++-
 examples/fips_validation/meson.build           |   1 +
 6 files changed, 356 insertions(+), 1 deletion(-)
 create mode 100644 examples/fips_validation/fips_validation_ccm.c

diff --git a/examples/fips_validation/Makefile b/examples/fips_validation/Makefile
index 77b15ae..7b1fe34 100644
--- a/examples/fips_validation/Makefile
+++ b/examples/fips_validation/Makefile
@@ -11,6 +11,7 @@ SRCS-y += fips_validation_hmac.c
 SRCS-y += fips_validation_tdes.c
 SRCS-y += fips_validation_gcm.c
 SRCS-y += fips_validation_cmac.c
+SRCS-y += fips_validation_ccm.c
 SRCS-y += main.c
 
 # Build using pkg-config variables if possible
diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index fdf6f64..a835cc3 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -121,6 +121,11 @@ fips_test_parse_header(void)
 			ret = parse_test_cmac_init();
 			if (ret < 0)
 				return 0;
+		} else if (strstr(info.vec[i], "CCM")) {
+			info.algo = FIPS_TEST_ALGO_AES_CCM;
+			ret = parse_test_ccm_init();
+			if (ret < 0)
+				return 0;
 		} else if (strstr(info.vec[i], "HMAC")) {
 			info.algo = FIPS_TEST_ALGO_HMAC;
 			ret = parse_test_hmac_init();
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index 8dffe8e..3e291bc 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -26,6 +26,7 @@ enum fips_test_algorithms {
 		FIPS_TEST_ALGO_AES = 0,
 		FIPS_TEST_ALGO_AES_GCM,
 		FIPS_TEST_ALGO_AES_CMAC,
+		FIPS_TEST_ALGO_AES_CCM,
 		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_MAX
@@ -102,6 +103,14 @@ enum fips_tdes_test_types {
 	TDES_MMT /* Multi block Message Test */
 };
 
+enum fips_ccm_test_types {
+	CCM_VADT	= 1, /* Variable Associated Data Test */
+	CCM_VPT,		 /* Variable Payload Test */
+	CCM_VNT,		 /* Variable Nonce Test */
+	CCM_VTT,		 /* Variable Tag Test */
+	CCM_DVPT,	 /*  Decryption-Verification Process Test */
+};
+
 struct aesavs_interim_data {
 	enum fips_aesavs_test_types test_type;
 	uint32_t cipher_algo;
@@ -117,6 +126,15 @@ struct tdes_interim_data {
 	uint32_t nb_keys;
 };
 
+struct ccm_interim_data {
+	enum fips_ccm_test_types test_type;
+	uint32_t aad_len;
+	uint32_t pt_len;
+	uint32_t digest_len;
+	uint32_t key_len;
+	uint32_t iv_len;
+};
+
 struct fips_test_interim_info {
 	FILE *fp_rd;
 	FILE *fp_wr;
@@ -131,6 +149,7 @@ struct fips_test_interim_info {
 		struct aesavs_interim_data aes_data;
 		struct hmac_interim_data hmac_data;
 		struct tdes_interim_data tdes_data;
+		struct ccm_interim_data ccm_data;
 
 	} interim_info;
 
@@ -179,6 +198,9 @@ int
 parse_test_cmac_init(void);
 
 int
+parse_test_ccm_init(void);
+
+int
 parser_read_uint8_hex(uint8_t *value, const char *p);
 
 int
diff --git a/examples/fips_validation/fips_validation_ccm.c b/examples/fips_validation/fips_validation_ccm.c
new file mode 100644
index 0000000..632999c
--- /dev/null
+++ b/examples/fips_validation/fips_validation_ccm.c
@@ -0,0 +1,272 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <rte_string_fns.h>
+#include <rte_cryptodev.h>
+#include <rte_malloc.h>
+
+#include "fips_validation.h"
+
+#define DVPT_STR	"CCM-DVPT"
+#define VADT_STR	"CCM-VADT"
+#define VPT_STR		"CCM-VPT"
+#define VNT_STR		"CCM-VNT"
+#define VTT_STR		"CCM-VTT"
+
+#define PARAM_PREFIX	"["
+#define ALEN_PREFIX	"Alen = "
+#define PLEN_PREFIX	"Plen = "
+#define IVLEN_PREFIX	"Nlen = "
+#define DIGESTL_PREFIX	"Tlen = "
+
+#define COUNT_STR	"Count = "
+#define KEY_STR		"Key = "
+#define IV_STR		"Nonce = "
+#define PT_STR		"Payload = "
+#define CT_STR		"CT = "
+#define AAD_STR		"Adata = "
+#define POS_NEG_STR	"Result = "
+
+#define POS_KEYWORD	"Pass"
+#define NEG_KEYWORD	"Fail"
+
+static int
+parser_dvpt_interim(const char *key, char *src, struct fips_val *val)
+{
+	char *tmp, c, value[10];
+	char num_pattern[] = "0123456789";
+	int i = 0;
+
+	memset(value, 0, 10);
+
+	tmp = strstr(src, key);
+	if (!tmp)
+		return -1;
+
+	tmp += strlen(key);
+
+	c = tmp[0];
+
+	while (strchr(num_pattern, c) && i < 10) {
+		value[i++] = c;
+		c = tmp[i];
+	}
+
+	return parser_read_uint32_val("", value, val);
+}
+
+static int
+parse_dvpt_ct_hex_str(const char *key, char *src, struct fips_val *val)
+{
+	int ret;
+
+	val->len = vec.pt.len;
+
+	ret = parse_uint8_known_len_hex_str(key, src, val);
+	if (ret < 0)
+		return ret;
+
+	src += strlen(key) + val->len * 2;
+
+	ret = parse_uint8_known_len_hex_str("", src, &vec.aead.digest);
+	if (ret < 0) {
+		rte_free(val->val);
+		memset(val, 0, sizeof(*val));
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+parse_uint8_ccm_aad_str(const char *key, char *src, struct fips_val *val)
+{
+	uint32_t len = val->len, j;
+
+	src += strlen(key);
+
+	/* CCM aad requires 18 bytes padding before the real content */
+	val->val = rte_zmalloc(NULL, len + 18, 0);
+	if (!val->val)
+		return -1;
+
+	for (j = 0; j < len; j++) {
+		char byte[3] = {src[j * 2], src[j * 2 + 1], '\0'};
+
+		if (parser_read_uint8_hex(&val->val[j + 18], byte) < 0) {
+			rte_free(val->val);
+			memset(val, 0, sizeof(*val));
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+struct fips_test_callback ccm_vnt_vec[] = {
+		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
+		{AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad},
+		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vnt_interim_vec[] = {
+		{ALEN_PREFIX, parser_read_uint32_val, &vec.aead.aad},
+		{PLEN_PREFIX, parser_read_uint32_val, &vec.pt},
+		{DIGESTL_PREFIX, parser_read_uint32_val, &vec.aead.digest},
+		{IVLEN_PREFIX, parser_read_uint32_val, &vec.iv},
+		{KEY_STR, parse_uint8_hex_str, &vec.aead.key},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vtt_vec[] = {
+		{AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad},
+		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vtt_interim_vec[] = {
+		{ALEN_PREFIX, parser_read_uint32_val, &vec.aead.aad},
+		{PLEN_PREFIX, parser_read_uint32_val, &vec.pt},
+		{IVLEN_PREFIX, parser_read_uint32_val, &vec.iv},
+		{DIGESTL_PREFIX, parser_read_uint32_val, &vec.aead.digest},
+		{KEY_STR, parse_uint8_hex_str, &vec.aead.key},
+		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vadt_vec[] = {
+		{AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad},
+		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vadt_interim_vec[] = {
+		{PLEN_PREFIX, parser_read_uint32_val, &vec.pt},
+		{IVLEN_PREFIX, parser_read_uint32_val, &vec.iv},
+		{ALEN_PREFIX, parser_read_uint32_val, &vec.aead.aad},
+		{DIGESTL_PREFIX, parser_read_uint32_val, &vec.aead.digest},
+		{KEY_STR, parse_uint8_hex_str, &vec.aead.key},
+		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vpt_vec[] = {
+		{AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad},
+		{PT_STR, parse_uint8_known_len_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_vpt_interim_vec[] = {
+		{ALEN_PREFIX, parser_read_uint32_val, &vec.aead.aad},
+		{IVLEN_PREFIX, parser_read_uint32_val, &vec.iv},
+		{DIGESTL_PREFIX, parser_read_uint32_val, &vec.aead.digest},
+		{PLEN_PREFIX, parser_read_uint32_val, &vec.pt},
+		{KEY_STR, parse_uint8_hex_str, &vec.aead.key},
+		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_dvpt_vec[] = {
+		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
+		{AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad},
+		{CT_STR, parse_dvpt_ct_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback ccm_dvpt_interim_vec[] = {
+		{ALEN_PREFIX, parser_dvpt_interim, &vec.aead.aad},
+		{PLEN_PREFIX, parser_dvpt_interim, &vec.pt},
+		{IVLEN_PREFIX, parser_dvpt_interim, &vec.iv},
+		{DIGESTL_PREFIX, parser_dvpt_interim, &vec.aead.digest},
+		{KEY_STR, parse_uint8_hex_str, &vec.aead.key},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct ccm_test_types {
+	const char *str;
+	uint32_t type;
+	const struct fips_test_callback *cb;
+	const struct fips_test_callback *cb_interim;
+	enum fips_test_op op;
+} ctt[] = {
+		{DVPT_STR, CCM_DVPT, ccm_dvpt_vec, ccm_dvpt_interim_vec,
+			FIPS_TEST_DEC_AUTH_VERIF},
+		{VPT_STR, CCM_VPT, ccm_vpt_vec, ccm_vpt_interim_vec,
+			FIPS_TEST_ENC_AUTH_GEN},
+		{VADT_STR, CCM_VADT, ccm_vadt_vec, ccm_vadt_interim_vec,
+			FIPS_TEST_ENC_AUTH_GEN},
+		{VNT_STR, CCM_VNT, ccm_vnt_vec, ccm_vnt_interim_vec,
+			FIPS_TEST_ENC_AUTH_GEN},
+		{VTT_STR, CCM_VTT, ccm_vtt_vec, ccm_vtt_interim_vec,
+			FIPS_TEST_ENC_AUTH_GEN},
+};
+
+static int
+parse_test_ccm_writeback(struct fips_val *val)
+{
+	struct fips_val tmp_val;
+
+	switch (info.interim_info.ccm_data.test_type) {
+	case CCM_DVPT:
+		fprintf(info.fp_wr, "%s", POS_NEG_STR);
+		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS) {
+			fprintf(info.fp_wr, "%s\n", POS_KEYWORD);
+			fprintf(info.fp_wr, "%s", PT_STR);
+
+			tmp_val.val = val->val;
+			tmp_val.len = vec.pt.len;
+
+			if (tmp_val.len == 0)
+				fprintf(info.fp_wr, "00\n");
+			else
+				parse_write_hex_str(&tmp_val);
+		} else
+			fprintf(info.fp_wr, "%s\n", NEG_KEYWORD);
+
+		break;
+
+	case CCM_VADT:
+	case CCM_VNT:
+	case CCM_VPT:
+	case CCM_VTT:
+		fprintf(info.fp_wr, "%s", CT_STR);
+
+		parse_write_hex_str(val);
+
+		break;
+
+	}
+
+	return 0;
+}
+
+int
+parse_test_ccm_init(void)
+{
+
+	uint32_t i;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		char *line = info.vec[i];
+		uint32_t j;
+
+		for (j = 0; j < RTE_DIM(ctt); j++)
+			if (strstr(line, ctt[j].str)) {
+				info.interim_info.ccm_data.test_type =
+						ctt[j].type;
+				info.callbacks = ctt[j].cb;
+				info.interim_callbacks = ctt[j].cb_interim;
+				info.op = ctt[j].op;
+				break;
+		}
+	}
+
+	info.parse_writeback = parse_test_ccm_writeback;
+
+	return 0;
+}
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index e953f3e..0a7e75f 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -470,7 +470,10 @@ prepare_aead_op(void)
 	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
 	rte_pktmbuf_reset(env.mbuf);
 
-	memcpy(iv, vec.iv.val, vec.iv.len);
+	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);
 
 	sym->m_src = env.mbuf;
 	sym->aead.data.offset = 0;
@@ -726,6 +729,52 @@ prepare_cmac_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_ccm_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_aead_xform *aead_xform = &xform->aead;
+
+	xform->type = RTE_CRYPTO_SYM_XFORM_AEAD;
+
+	aead_xform->algo = RTE_CRYPTO_AEAD_AES_CCM;
+	aead_xform->aad_length = vec.aead.aad.len;
+	aead_xform->digest_length = vec.aead.digest.len;
+	aead_xform->iv.offset = IV_OFF;
+	aead_xform->iv.length = vec.iv.len;
+	aead_xform->key.data = vec.aead.key.val;
+	aead_xform->key.length = vec.aead.key.len;
+	aead_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_AEAD_OP_ENCRYPT :
+			RTE_CRYPTO_AEAD_OP_DECRYPT;
+
+	cap_idx.algo.aead = aead_xform->algo;
+	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
+
+	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_aead(cap,
+			aead_xform->key.length,
+			aead_xform->digest_length, aead_xform->aad_length,
+			aead_xform->iv.length) != 0) {
+		RTE_LOG(ERR, USER1,
+			"PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n",
+				info.device_name, aead_xform->key.length,
+				aead_xform->digest_length,
+				aead_xform->aad_length,
+				aead_xform->iv.length);
+		return -EPERM;
+	}
+
+	return 0;
+}
+
 static void
 get_writeback_data(struct fips_val *val)
 {
@@ -1091,6 +1140,11 @@ init_test_ops(void)
 		test_ops.prepare_xform = prepare_cmac_xform;
 		test_ops.test = fips_generic_test;
 		break;
+	case FIPS_TEST_ALGO_AES_CCM:
+		test_ops.prepare_op = prepare_aead_op;
+		test_ops.prepare_xform = prepare_ccm_xform;
+		test_ops.test = fips_generic_test;
+		break;
 	default:
 		return -1;
 	}
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
index a0d38fa..498c9ba 100644
--- a/examples/fips_validation/meson.build
+++ b/examples/fips_validation/meson.build
@@ -15,5 +15,6 @@ sources = files(
 	'fips_validation_tdes.c',
 	'fips_validation_gcm.c',
 	'fips_validation_cmac.c',
+	'fips_validation_ccm.c',
 	'main.c'
 )
-- 
2.9.5

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

* [dpdk-dev] [PATCH v7 8/8] doc: add fips validation application guide
  2018-11-02  9:55     ` [dpdk-dev] [PATCH v7 " Kovacevic, Marko
                         ` (6 preceding siblings ...)
  2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 7/8] examples/fips_validation: support CCM parsing Kovacevic, Marko
@ 2018-11-02  9:55       ` Kovacevic, Marko
  2018-11-02 11:23       ` [dpdk-dev] [PATCH v7 0/8] FIPS validation capability Akhil Goyal
  8 siblings, 0 replies; 52+ messages in thread
From: Kovacevic, Marko @ 2018-11-02  9:55 UTC (permalink / raw)
  To: akhil.goyal; +Cc: dev, roy.fan.zhang, arkadiuszx.kusztal, Kovacevic, Marko

Document explains how to run the fips sample app
and instructions users need to parser all the request
files and generate the response files.

Signed-off-by: Marko Kovacevic <marko.kovacevic@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusztal@intel.com>
---
 doc/guides/rel_notes/release_18_11.rst       |   5 +
 doc/guides/sample_app_ug/fips_validation.rst | 132 +++++++++++++++++++++++++++
 doc/guides/sample_app_ug/index.rst           |   1 +
 3 files changed, 138 insertions(+)
 create mode 100644 doc/guides/sample_app_ug/fips_validation.rst

diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index 376128f..8fa0441 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -285,6 +285,11 @@ New Features
   this application doesn't need to launch dedicated worker threads for vhost
   enqueue/dequeue operations.
 
+* **Added Cryptodev Fips Validation Example Application.**
+
+  Added an example application to parse and perform symmetric cryptography
+  computation to the NIST Cryptographic Algorithm Validation Program (CAVP)
+  test vectors.
 
 API Changes
 -----------
diff --git a/doc/guides/sample_app_ug/fips_validation.rst b/doc/guides/sample_app_ug/fips_validation.rst
new file mode 100644
index 0000000..aeacfac
--- /dev/null
+++ b/doc/guides/sample_app_ug/fips_validation.rst
@@ -0,0 +1,132 @@
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(c) 2018 Intel Corporation.
+
+Federal Information Processing Standards (FIPS) CryptoDev Validation
+====================================================================
+
+Overview
+--------
+
+Federal Information Processing Standards (FIPS) are publicly announced standards
+developed by the United States federal government for use in computer systems by
+non-military government agencies and government contractors.
+
+This application is used to parse and perform symmetric cryptography
+computation to the NIST Cryptographic Algorithm Validation Program (CAVP) test
+vectors.
+
+For an algorithm implementation to be listed on a cryptographic module
+validation certificate as an Approved security function, the algorithm
+implementation must meet all the requirements of FIPS 140-2 and must
+successfully complete the cryptographic algorithm validation process.
+
+Limitations
+-----------
+
+* Only NIST CAVP request files are parsed by this application.
+* The version of request file supported is ``CAVS 21.0``
+* If the header comment in a ``.req`` file does not contain a Algo tag
+  i.e ``AES,TDES,GCM`` you need to manually add it into the header comment for
+  example::
+
+      # VARIABLE KEY - KAT for CBC / # TDES VARIABLE KEY - KAT for CBC
+
+* The application does not supply the test vectors. The user is expected to
+  obtain the test vector files from `NIST
+  <https://csrc.nist.gov/projects/cryptographic-algorithm-validation-
+  program/block-ciphers>`_ website. To obtain the ``.req`` files you need to
+  email a person from the NIST website and pay for the ``.req`` files.
+  The ``.rsp`` files from the site can be used to validate and compare with
+  the ``.rsp`` files created by the FIPS application.
+
+* Supported test vectors
+    * AES-CBC (128,192,256) - GFSbox, KeySbox, MCT, MMT
+    * AES-GCM (128,192,256) - EncryptExtIV, Decrypt
+    * AES-CCM (128) - VADT, VNT, VPT, VTT, DVPT
+    * AES-CMAC (128) - Generate, Verify
+    * HMAC (SHA1, SHA224, SHA256, SHA384, SHA512)
+    * TDES-CBC (1 Key, 2 Keys, 3 Keys) - MMT, Monte, Permop, Subkey, Varkey,
+      VarText
+
+Application Information
+-----------------------
+
+If a ``.req`` is used as the input file after the application is finished
+running it will generate a response file or ``.rsp``. Differences between the
+two files are, the ``.req`` file has missing information for instance if doing
+encryption you will not have the cipher text and that will be generated in the
+response file. Also if doing decryption it will not have the plain text until it
+finished the work and in the response file it will be added onto the end of each
+operation.
+
+The application can be run with a ``.rsp`` file and what the outcome of that
+will be is it will add a extra line in the generated ``.rsp`` which should be
+the same as the ``.rsp`` used to run the application, this is useful for
+validating if the application has done the operation correctly.
+
+
+Compiling the Application
+-------------------------
+
+* Compile Application
+
+    .. code-block:: console
+
+         make -C examples/fips_validation
+
+*  Run ``dos2unix`` on the request files
+
+    .. code-block:: console
+
+         dos2unix AES/req/*
+         dos2unix AES_GCM/req/*
+         dos2unix CCM/req/*
+         dos2unix CMAC/req/*
+         dos2unix HMAC/req/*
+         dos2unix TDES/req/*
+
+Running the Application
+-----------------------
+
+The application requires a number of command line options:
+
+    .. code-block:: console
+
+         ./fips_validation [EAL options]
+         -- --req-file FILE_PATH/FOLDER_PATH
+         --rsp-file FILE_PATH/FOLDER_PATH
+         [--cryptodev DEVICE_NAME] [--cryptodev-id ID] [--path-is-folder]
+
+where,
+  * req-file: The path of the request file or folder, separated by
+    ``path-is-folder`` option.
+
+  * rsp-file: The path that the response file or folder is stored. separated by
+    ``path-is-folder`` option.
+
+  * cryptodev: The name of the target DPDK Crypto device to be validated.
+
+  * cryptodev-id: The id of the target DPDK Crypto device to be validated.
+
+  * path-is-folder: If presented the application expects req-file and rsp-file
+    are folder paths.
+
+
+To run the application in linuxapp environment to test one AES FIPS test data
+file for crypto_aesni_mb PMD, issue the command:
+
+.. code-block:: console
+
+    $ ./fips_validation --vdev crypto_aesni_mb --
+    --req-file /PATH/TO/REQUEST/FILE.req --rsp-file ./PATH/TO/RESPONSE/FILE.rsp
+    --cryptodev crypto_aesni_mb
+
+To run the application in linuxapp environment to test all AES-GCM FIPS test
+data files in one folder for crypto_aesni_gcm PMD, issue the command:
+
+.. code-block:: console
+
+    $ ./fips_validation --vdev crypto_aesni_gcm0 --
+    --req-file /PATH/TO/REQUEST/FILE/FOLDER/
+    --rsp-file ./PATH/TO/RESPONSE/FILE/FOLDER/
+    --cryptodev-id 0 --path-is-folder
diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst
index 74b12af..65c12d9 100644
--- a/doc/guides/sample_app_ug/index.rst
+++ b/doc/guides/sample_app_ug/index.rst
@@ -57,6 +57,7 @@ Sample Applications User Guides
     performance_thread
     ipsec_secgw
     bbdev_app
+    fips_validation
 
 **Figures**
 
-- 
2.9.5

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

* Re: [dpdk-dev] [PATCH v7 0/8] FIPS validation capability
  2018-11-02  9:55     ` [dpdk-dev] [PATCH v7 " Kovacevic, Marko
                         ` (7 preceding siblings ...)
  2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 8/8] doc: add fips validation application guide Kovacevic, Marko
@ 2018-11-02 11:23       ` Akhil Goyal
  2018-11-02 11:34         ` Akhil Goyal
  8 siblings, 1 reply; 52+ messages in thread
From: Akhil Goyal @ 2018-11-02 11:23 UTC (permalink / raw)
  To: Kovacevic, Marko; +Cc: dev, roy.fan.zhang, arkadiuszx.kusztal



On 11/2/2018 3:25 PM, Kovacevic, Marko wrote:
> This sample application is made for the purpose so that users of DPDK
> who wish to get FIPS certification for their platforms, this sample app enables
> users to parse test vectors that is gotten from NIST and be able to get
> a generated response file which they can then verify and be sure their
> system will pass FIPS certification.
>
> Kovacevic, Marko (8):
> v7:
>    - Fixed compilation issue.
> v6:
>    - Added MAINTAINER file into different patch
>    - Udpated documentation
>    - Changed app name and file location
>    - Fixed memory leak in TDES
>    - Changed patch titles
>    - Made other changes from comments
> v5:
>    - Changed patch titles
>    - Added MAINTAINERS File
>    - Removed bus_pci Dependency
>    - Updated documentation
>    - Changed app name
> v4:
> - Added Limitation
> - Changed TDES BLOCK SIZE from 16 -> 8
>    as DES block size is 64bits (main.c)
> v3:
> - Fixed a no-testing bug
> - Fixed some code style issue
>
> v2:
> - Refactor the code.
> - Move the code from test to sample applcation
>
>    examples/fips_validation: add cryptodev fips compliant application
>    examples/fips_validation: support AES parsing
>    examples/fips_validation: support HMAC parsing
>    examples/fips_validation: support TDES parsing
>    examples/fips_validation: support GCM parsing
>    examples/fips_validation: support CMAC parsing
>    examples/fips_validation: support CCM parsing
>    doc: add fips validation application guide
>
>   MAINTAINERS                                     |    4 +
>   doc/guides/rel_notes/release_18_11.rst          |    5 +
>   doc/guides/sample_app_ug/fips_validation.rst    |  132 +++
>   doc/guides/sample_app_ug/index.rst              |    1 +
>   examples/fips_validation/Makefile               |   75 ++
>   examples/fips_validation/fips_validation.c      |  595 +++++++++++
>   examples/fips_validation/fips_validation.h      |  233 +++++
>   examples/fips_validation/fips_validation_aes.c  |  188 ++++
>   examples/fips_validation/fips_validation_ccm.c  |  272 +++++
>   examples/fips_validation/fips_validation_cmac.c |  116 +++
>   examples/fips_validation/fips_validation_gcm.c  |  125 +++
>   examples/fips_validation/fips_validation_hmac.c |  105 ++
>   examples/fips_validation/fips_validation_tdes.c |  264 +++++
>   examples/fips_validation/main.c                 | 1221 +++++++++++++++++++++++
>   examples/fips_validation/meson.build            |   20 +
>   15 files changed, 3356 insertions(+)
>   create mode 100644 doc/guides/sample_app_ug/fips_validation.rst
>   create mode 100644 examples/fips_validation/Makefile
>   create mode 100644 examples/fips_validation/fips_validation.c
>   create mode 100644 examples/fips_validation/fips_validation.h
>   create mode 100644 examples/fips_validation/fips_validation_aes.c
>   create mode 100644 examples/fips_validation/fips_validation_ccm.c
>   create mode 100644 examples/fips_validation/fips_validation_cmac.c
>   create mode 100644 examples/fips_validation/fips_validation_gcm.c
>   create mode 100644 examples/fips_validation/fips_validation_hmac.c
>   create mode 100644 examples/fips_validation/fips_validation_tdes.c
>   create mode 100644 examples/fips_validation/main.c
>   create mode 100644 examples/fips_validation/meson.build
>
Series Reviewed-by: Akhil Goyal <akhil.goyal@nxp.com>

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

* Re: [dpdk-dev] [PATCH v7 0/8] FIPS validation capability
  2018-11-02 11:23       ` [dpdk-dev] [PATCH v7 0/8] FIPS validation capability Akhil Goyal
@ 2018-11-02 11:34         ` Akhil Goyal
  0 siblings, 0 replies; 52+ messages in thread
From: Akhil Goyal @ 2018-11-02 11:34 UTC (permalink / raw)
  To: Kovacevic, Marko; +Cc: dev, roy.fan.zhang, arkadiuszx.kusztal



On 11/2/2018 4:53 PM, Akhil Goyal wrote:
>
> On 11/2/2018 3:25 PM, Kovacevic, Marko wrote:
>> This sample application is made for the purpose so that users of DPDK
>> who wish to get FIPS certification for their platforms, this sample app enables
>> users to parse test vectors that is gotten from NIST and be able to get
>> a generated response file which they can then verify and be sure their
>> system will pass FIPS certification.
>>
>> Kovacevic, Marko (8):
>> v7:
>>     - Fixed compilation issue.
>> v6:
>>     - Added MAINTAINER file into different patch
>>     - Udpated documentation
>>     - Changed app name and file location
>>     - Fixed memory leak in TDES
>>     - Changed patch titles
>>     - Made other changes from comments
>> v5:
>>     - Changed patch titles
>>     - Added MAINTAINERS File
>>     - Removed bus_pci Dependency
>>     - Updated documentation
>>     - Changed app name
>> v4:
>> - Added Limitation
>> - Changed TDES BLOCK SIZE from 16 -> 8
>>     as DES block size is 64bits (main.c)
>> v3:
>> - Fixed a no-testing bug
>> - Fixed some code style issue
>>
>> v2:
>> - Refactor the code.
>> - Move the code from test to sample applcation
>>
>>     examples/fips_validation: add cryptodev fips compliant application
>>     examples/fips_validation: support AES parsing
>>     examples/fips_validation: support HMAC parsing
>>     examples/fips_validation: support TDES parsing
>>     examples/fips_validation: support GCM parsing
>>     examples/fips_validation: support CMAC parsing
>>     examples/fips_validation: support CCM parsing
>>     doc: add fips validation application guide
>>
>>    MAINTAINERS                                     |    4 +
>>    doc/guides/rel_notes/release_18_11.rst          |    5 +
>>    doc/guides/sample_app_ug/fips_validation.rst    |  132 +++
>>    doc/guides/sample_app_ug/index.rst              |    1 +
>>    examples/fips_validation/Makefile               |   75 ++
>>    examples/fips_validation/fips_validation.c      |  595 +++++++++++
>>    examples/fips_validation/fips_validation.h      |  233 +++++
>>    examples/fips_validation/fips_validation_aes.c  |  188 ++++
>>    examples/fips_validation/fips_validation_ccm.c  |  272 +++++
>>    examples/fips_validation/fips_validation_cmac.c |  116 +++
>>    examples/fips_validation/fips_validation_gcm.c  |  125 +++
>>    examples/fips_validation/fips_validation_hmac.c |  105 ++
>>    examples/fips_validation/fips_validation_tdes.c |  264 +++++
>>    examples/fips_validation/main.c                 | 1221 +++++++++++++++++++++++
>>    examples/fips_validation/meson.build            |   20 +
>>    15 files changed, 3356 insertions(+)
>>    create mode 100644 doc/guides/sample_app_ug/fips_validation.rst
>>    create mode 100644 examples/fips_validation/Makefile
>>    create mode 100644 examples/fips_validation/fips_validation.c
>>    create mode 100644 examples/fips_validation/fips_validation.h
>>    create mode 100644 examples/fips_validation/fips_validation_aes.c
>>    create mode 100644 examples/fips_validation/fips_validation_ccm.c
>>    create mode 100644 examples/fips_validation/fips_validation_cmac.c
>>    create mode 100644 examples/fips_validation/fips_validation_gcm.c
>>    create mode 100644 examples/fips_validation/fips_validation_hmac.c
>>    create mode 100644 examples/fips_validation/fips_validation_tdes.c
>>    create mode 100644 examples/fips_validation/main.c
>>    create mode 100644 examples/fips_validation/meson.build
>>
> Series Reviewed-by: Akhil Goyal <akhil.goyal@nxp.com>
Applied to dpdk-next-crypto

Thanks

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

end of thread, other threads:[~2018-11-02 11:34 UTC | newest]

Thread overview: 52+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-12 14:44 [dpdk-dev] [PATCH v4 0/8] FIPS validation capability Marko Kovacevic
2018-10-12 14:44 ` [dpdk-dev] [PATCH v4 1/8] examples: add fips validation into examples Marko Kovacevic
2018-10-12 14:44 ` [dpdk-dev] [PATCH v4 2/8] examples: add aes parser and enablement for test types Marko Kovacevic
2018-10-12 14:44 ` [dpdk-dev] [PATCH v4 3/8] examples: add hmac parser Marko Kovacevic
2018-10-12 14:44 ` [dpdk-dev] [PATCH v4 4/8] examples: add TDES parser and enablement for test types Marko Kovacevic
2018-10-12 14:44 ` [dpdk-dev] [PATCH v4 5/8] examples: add gcm parser Marko Kovacevic
2018-10-12 14:44 ` [dpdk-dev] [PATCH v4 6/8] examples: add cmac parser and enablement for test types Marko Kovacevic
2018-10-12 14:45 ` [dpdk-dev] [PATCH v4 7/8] examples: add ccm " Marko Kovacevic
2018-10-12 14:45 ` [dpdk-dev] [PATCH v4 8/8] doc: add guides for fips validation Marko Kovacevic
2018-10-15  6:36 ` [dpdk-dev] [PATCH v4 0/8] FIPS validation capability Kusztal, ArkadiuszX
2018-10-16 14:40 ` Akhil Goyal
2018-10-17 12:49 ` [dpdk-dev] [PATCH v5 " Marko Kovacevic
2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 1/8] examples/cryptodev_fips_validate: add fips validation into examples Marko Kovacevic
2018-10-24 12:13     ` Akhil Goyal
2018-10-24 14:17       ` Marko Kovacevic
2018-10-24 14:36         ` Akhil Goyal
2018-10-24 15:13           ` Marko Kovacevic
2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 2/8] examples/cryptodev_fips_validate: add aes parser and enablement for test types Marko Kovacevic
2018-10-24 12:37     ` Akhil Goyal
2018-10-24 14:18       ` Marko Kovacevic
2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 3/8] examples/cryptodev_fips_validate: add hmac parser Marko Kovacevic
2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 4/8] examples/cryptodev_fips_validate: add TDES parser and enablement for test types Marko Kovacevic
2018-10-24 12:31     ` Akhil Goyal
2018-10-24 14:11       ` Marko Kovacevic
2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 5/8] examples/cryptodev_fips_validate: add gcm parser Marko Kovacevic
2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 6/8] examples/cryptodev_fips_validate: add cmac parser and enablement for test types Marko Kovacevic
2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 7/8] examples/cryptodev_fips_validate: add ccm " Marko Kovacevic
2018-10-17 12:49   ` [dpdk-dev] [PATCH v5 8/8] doc/guides/sample_app_ug: add guides for fips validation Marko Kovacevic
2018-10-24 12:51     ` Akhil Goyal
2018-10-24 11:42   ` [dpdk-dev] [PATCH v5 0/8] FIPS validation capability Akhil Goyal
2018-10-26 11:07   ` [dpdk-dev] [PATCH v6 " Marko Kovacevic
2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 1/8] examples/fips_validation: add cryptodev fips compliant application Marko Kovacevic
2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 2/8] examples/fips_validation: support AES parsing Marko Kovacevic
2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 3/8] examples/fips_validation: support HMAC parsing Marko Kovacevic
2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 4/8] examples/fips_validation: support TDES parsing Marko Kovacevic
2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 5/8] examples/fips_validation: support GCM parsing Marko Kovacevic
2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 6/8] examples/fips_validation: support CMAC parsing Marko Kovacevic
2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 7/8] examples/fips_validation: support CCM parsing Marko Kovacevic
2018-10-26 11:07     ` [dpdk-dev] [PATCH v6 8/8] doc: add fips validation application guide Marko Kovacevic
2018-11-02  9:17     ` [dpdk-dev] [PATCH v6 0/8] FIPS validation capability Akhil Goyal
2018-11-02  9:34       ` Kovacevic, Marko
2018-11-02  9:55     ` [dpdk-dev] [PATCH v7 " Kovacevic, Marko
2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 1/8] examples/fips_validation: add cryptodev fips compliant application Kovacevic, Marko
2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 2/8] examples/fips_validation: support AES parsing Kovacevic, Marko
2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 3/8] examples/fips_validation: support HMAC parsing Kovacevic, Marko
2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 4/8] examples/fips_validation: support TDES parsing Kovacevic, Marko
2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 5/8] examples/fips_validation: support GCM parsing Kovacevic, Marko
2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 6/8] examples/fips_validation: support CMAC parsing Kovacevic, Marko
2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 7/8] examples/fips_validation: support CCM parsing Kovacevic, Marko
2018-11-02  9:55       ` [dpdk-dev] [PATCH v7 8/8] doc: add fips validation application guide Kovacevic, Marko
2018-11-02 11:23       ` [dpdk-dev] [PATCH v7 0/8] FIPS validation capability Akhil Goyal
2018-11-02 11:34         ` 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).