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.kovace...@intel.com>
Signed-off-by: Fan Zhang <roy.fan.zh...@intel.com>
Acked-by: Arek Kusztal <arkadiuszx.kusz...@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'
+)

Reply via email to