common/iavf: support raw packet in protocol header
[dpdk.git] / examples / fips_validation / main.c
index 6a1cea3..332a411 100644 (file)
@@ -7,7 +7,7 @@
 #include <dirent.h>
 
 #include <rte_cryptodev.h>
-#include <rte_cryptodev_pmd.h>
+#include <rte_malloc.h>
 #include <rte_mempool.h>
 #include <rte_mbuf.h>
 #include <rte_string_fns.h>
 #include "fips_validation.h"
 #include "fips_dev_self_test.h"
 
-#define REQ_FILE_PATH_KEYWORD  "req-file"
-#define RSP_FILE_PATH_KEYWORD  "rsp-file"
-#define MBUF_DATAROOM_KEYWORD  "mbuf-dataroom"
-#define FOLDER_KEYWORD         "path-is-folder"
-#define CRYPTODEV_KEYWORD      "cryptodev"
-#define CRYPTODEV_ID_KEYWORD   "cryptodev-id"
-#define CRYPTODEV_ST_KEYWORD   "self-test"
-#define CRYPTODEV_BK_ID_KEYWORD        "broken-test-id"
-#define CRYPTODEV_BK_DIR_KEY   "broken-test-dir"
-#define CRYPTODEV_ENC_KEYWORD  "enc"
-#define CRYPTODEV_DEC_KEYWORD  "dec"
+enum {
+#define OPT_REQ_FILE_PATH           "req-file"
+       OPT_REQ_FILE_PATH_NUM = 256,
+#define OPT_RSP_FILE_PATH           "rsp-file"
+       OPT_RSP_FILE_PATH_NUM,
+#define OPT_MBUF_DATAROOM           "mbuf-dataroom"
+       OPT_MBUF_DATAROOM_NUM,
+#define OPT_FOLDER                  "path-is-folder"
+       OPT_FOLDER_NUM,
+#define OPT_CRYPTODEV               "cryptodev"
+       OPT_CRYPTODEV_NUM,
+#define OPT_CRYPTODEV_ID            "cryptodev-id"
+       OPT_CRYPTODEV_ID_NUM,
+#define OPT_CRYPTODEV_ST            "self-test"
+       OPT_CRYPTODEV_ST_NUM,
+#define OPT_CRYPTODEV_BK_ID         "broken-test-id"
+       OPT_CRYPTODEV_BK_ID_NUM,
+#define OPT_CRYPTODEV_BK_DIR_KEY    "broken-test-dir"
+       OPT_CRYPTODEV_BK_DIR_KEY_NUM,
+#define OPT_USE_JSON                "use-json"
+       OPT_USE_JSON_NUM,
+};
 
 struct fips_test_vector vec;
 struct fips_test_interim_info info;
 
+#ifdef RTE_HAS_JANSSON
+struct fips_test_json_info json_info;
+#endif /* RTE_HAS_JANSSON */
+
 struct cryptodev_fips_validate_env {
        const char *req_path;
        const char *rsp_path;
@@ -64,10 +79,7 @@ cryptodev_fips_validate_app_int(void)
        if (env.self_test) {
                ret = fips_dev_self_test(env.dev_id, env.broken_test_config);
                if (ret < 0) {
-                       struct rte_cryptodev *cryptodev =
-                                       rte_cryptodev_pmd_get_dev(env.dev_id);
-
-                       rte_cryptodev_pmd_destroy(cryptodev);
+                       rte_cryptodev_close(env.dev_id);
 
                        return ret;
                }
@@ -128,17 +140,18 @@ cryptodev_fips_validate_app_int(void)
        if (ret < 0)
                goto error_exit;
 
+       ret = rte_cryptodev_start(env.dev_id);
+       if (ret < 0)
+               goto error_exit;
+
        return 0;
 
 error_exit:
 
        rte_mempool_free(env.mpool);
-       if (env.sess_mpool)
-               rte_mempool_free(env.sess_mpool);
-       if (env.sess_priv_mpool)
-               rte_mempool_free(env.sess_priv_mpool);
-       if (env.op_pool)
-               rte_mempool_free(env.op_pool);
+       rte_mempool_free(env.sess_mpool);
+       rte_mempool_free(env.sess_priv_mpool);
+       rte_mempool_free(env.op_pool);
 
        return ret;
 }
@@ -159,6 +172,11 @@ cryptodev_fips_validate_app_uninit(void)
 static int
 fips_test_one_file(void);
 
+#ifdef RTE_HAS_JANSSON
+static int
+fips_test_one_json_file(void);
+#endif /* RTE_HAS_JANSSON */
+
 static int
 parse_cryptodev_arg(char *arg)
 {
@@ -187,7 +205,7 @@ parse_cryptodev_id_arg(char *arg)
        }
 
 
-       if (!rte_cryptodev_pmd_is_valid_dev(cryptodev_id)) {
+       if (!rte_cryptodev_is_valid_dev(cryptodev_id)) {
                RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n",
                                cryptodev_id, arg);
                return -1;
@@ -212,10 +230,10 @@ cryptodev_fips_validate_usage(const char *prgname)
                "  --%s: self test indicator\n"
                "  --%s: self broken test ID\n"
                "  --%s: self broken test direction\n",
-               prgname, REQ_FILE_PATH_KEYWORD, RSP_FILE_PATH_KEYWORD,
-               FOLDER_KEYWORD, MBUF_DATAROOM_KEYWORD, def_mbuf_seg_size,
-               CRYPTODEV_KEYWORD, CRYPTODEV_ID_KEYWORD, CRYPTODEV_ST_KEYWORD,
-               CRYPTODEV_BK_ID_KEYWORD, CRYPTODEV_BK_DIR_KEY);
+               prgname, OPT_REQ_FILE_PATH, OPT_RSP_FILE_PATH,
+               OPT_FOLDER, OPT_MBUF_DATAROOM, def_mbuf_seg_size,
+               OPT_CRYPTODEV, OPT_CRYPTODEV_ID, OPT_CRYPTODEV_ST,
+               OPT_CRYPTODEV_BK_ID, OPT_CRYPTODEV_BK_DIR_KEY);
 }
 
 static int
@@ -226,16 +244,25 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
        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},
-                       {MBUF_DATAROOM_KEYWORD, required_argument, 0, 0},
-                       {CRYPTODEV_KEYWORD, required_argument, 0, 0},
-                       {CRYPTODEV_ID_KEYWORD, required_argument, 0, 0},
-                       {CRYPTODEV_ST_KEYWORD, no_argument, 0, 0},
-                       {CRYPTODEV_BK_ID_KEYWORD, required_argument, 0, 0},
-                       {CRYPTODEV_BK_DIR_KEY, required_argument, 0, 0},
-                       {NULL, 0, 0, 0}
+               {OPT_REQ_FILE_PATH, required_argument,
+                               NULL, OPT_REQ_FILE_PATH_NUM},
+               {OPT_RSP_FILE_PATH, required_argument,
+                               NULL, OPT_RSP_FILE_PATH_NUM},
+               {OPT_FOLDER, no_argument,
+                               NULL, OPT_FOLDER_NUM},
+               {OPT_MBUF_DATAROOM, required_argument,
+                               NULL, OPT_MBUF_DATAROOM_NUM},
+               {OPT_CRYPTODEV, required_argument,
+                               NULL, OPT_CRYPTODEV_NUM},
+               {OPT_CRYPTODEV_ID, required_argument,
+                               NULL, OPT_CRYPTODEV_ID_NUM},
+               {OPT_CRYPTODEV_ST, no_argument,
+                               NULL, OPT_CRYPTODEV_ST_NUM},
+               {OPT_CRYPTODEV_BK_ID, required_argument,
+                               NULL, OPT_CRYPTODEV_BK_ID_NUM},
+               {OPT_CRYPTODEV_BK_DIR_KEY, required_argument,
+                               NULL, OPT_CRYPTODEV_BK_DIR_KEY_NUM},
+               {NULL, 0, 0, 0}
        };
 
        argvopt = argv;
@@ -252,104 +279,104 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
                                  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 if (strcmp(lgopts[option_index].name,
-                                       CRYPTODEV_ST_KEYWORD) == 0) {
-                               env.self_test = 1;
-                       } else if (strcmp(lgopts[option_index].name,
-                                       CRYPTODEV_BK_ID_KEYWORD) == 0) {
-                               if (!env.broken_test_config) {
-                                       env.broken_test_config = rte_malloc(
-                                               NULL,
-                                               sizeof(*env.broken_test_config),
-                                               0);
-                                       if (!env.broken_test_config)
-                                               return -ENOMEM;
-
-                                       env.broken_test_config->expect_fail_dir =
-                                               self_test_dir_enc_auth_gen;
-                               }
+               case OPT_REQ_FILE_PATH_NUM:
+                       env.req_path = optarg;
+                       break;
 
-                               if (parser_read_uint32(
-                                       &env.broken_test_config->expect_fail_test_idx,
-                                               optarg) < 0) {
-                                       rte_free(env.broken_test_config);
-                                       cryptodev_fips_validate_usage(prgname);
-                                       return -EINVAL;
-                               }
-                       } else if (strcmp(lgopts[option_index].name,
-                                       CRYPTODEV_BK_DIR_KEY) == 0) {
-                               if (!env.broken_test_config) {
-                                       env.broken_test_config = rte_malloc(
-                                               NULL,
-                                               sizeof(*env.broken_test_config),
-                                               0);
-                                       if (!env.broken_test_config)
-                                               return -ENOMEM;
-
-                                       env.broken_test_config->
-                                               expect_fail_test_idx = 0;
-                               }
+               case OPT_RSP_FILE_PATH_NUM:
+                       env.rsp_path = optarg;
+                       break;
 
-                               if (strcmp(optarg, CRYPTODEV_ENC_KEYWORD) == 0)
-                                       env.broken_test_config->expect_fail_dir =
-                                               self_test_dir_enc_auth_gen;
-                               else if (strcmp(optarg, CRYPTODEV_DEC_KEYWORD)
-                                               == 0)
-                                       env.broken_test_config->expect_fail_dir =
-                                               self_test_dir_dec_auth_verify;
-                               else {
-                                       rte_free(env.broken_test_config);
-                                       cryptodev_fips_validate_usage(prgname);
-                                       return -EINVAL;
-                               }
-                       } else if (strcmp(lgopts[option_index].name,
-                                       MBUF_DATAROOM_KEYWORD) == 0) {
-                               uint32_t data_room_size;
-
-                               if (parser_read_uint32(&data_room_size,
-                                               optarg) < 0) {
-                                       cryptodev_fips_validate_usage(prgname);
-                                       return -EINVAL;
-                               }
+               case OPT_FOLDER_NUM:
+                       env.is_path_folder = 1;
+                       break;
 
-                               if (data_room_size == 0 ||
-                                               data_room_size > UINT16_MAX) {
-                                       cryptodev_fips_validate_usage(prgname);
-                                       return -EINVAL;
-                               }
+               case OPT_CRYPTODEV_NUM:
+                       ret = parse_cryptodev_arg(optarg);
+                       if (ret < 0) {
+                               cryptodev_fips_validate_usage(prgname);
+                               return -EINVAL;
+                       }
+                       break;
 
-                               env.mbuf_data_room = data_room_size;
-                       } else {
+               case OPT_CRYPTODEV_ID_NUM:
+                       ret = parse_cryptodev_id_arg(optarg);
+                       if (ret < 0) {
+                               cryptodev_fips_validate_usage(prgname);
+                               return -EINVAL;
+                       }
+                       break;
+
+               case OPT_CRYPTODEV_ST_NUM:
+                       env.self_test = 1;
+                       break;
+
+               case OPT_CRYPTODEV_BK_ID_NUM:
+                       if (!env.broken_test_config) {
+                               env.broken_test_config = rte_malloc(
+                                       NULL,
+                                       sizeof(*env.broken_test_config),
+                                       0);
+                               if (!env.broken_test_config)
+                                       return -ENOMEM;
+
+                               env.broken_test_config->expect_fail_dir =
+                                       self_test_dir_enc_auth_gen;
+                       }
+
+                       if (parser_read_uint32(
+                               &env.broken_test_config->expect_fail_test_idx,
+                                       optarg) < 0) {
+                               rte_free(env.broken_test_config);
+                               cryptodev_fips_validate_usage(prgname);
+                               return -EINVAL;
+                       }
+                       break;
+
+               case OPT_CRYPTODEV_BK_DIR_KEY_NUM:
+                       if (!env.broken_test_config) {
+                               env.broken_test_config = rte_malloc(
+                                       NULL,
+                                       sizeof(*env.broken_test_config),
+                                       0);
+                               if (!env.broken_test_config)
+                                       return -ENOMEM;
+
+                               env.broken_test_config->expect_fail_test_idx =
+                                       0;
+                       }
+
+                       if (strcmp(optarg, "enc") == 0)
+                               env.broken_test_config->expect_fail_dir =
+                                       self_test_dir_enc_auth_gen;
+                       else if (strcmp(optarg, "dec")
+                                       == 0)
+                               env.broken_test_config->expect_fail_dir =
+                                       self_test_dir_dec_auth_verify;
+                       else {
+                               rte_free(env.broken_test_config);
                                cryptodev_fips_validate_usage(prgname);
                                return -EINVAL;
                        }
                        break;
+
+
+               case OPT_MBUF_DATAROOM_NUM:
+                       if (parser_read_uint16(&env.mbuf_data_room,
+                                       optarg) < 0) {
+                               cryptodev_fips_validate_usage(prgname);
+                               return -EINVAL;
+                       }
+
+                       if (env.mbuf_data_room == 0) {
+                               cryptodev_fips_validate_usage(prgname);
+                               return -EINVAL;
+                       }
+                       break;
+
                default:
-                       return -1;
+                       cryptodev_fips_validate_usage(prgname);
+                       return -EINVAL;
                }
        }
 
@@ -409,8 +436,17 @@ main(int argc, char *argv[])
                        goto exit;
                }
 
-
+#ifdef RTE_HAS_JANSSON
+               if (info.file_type == FIPS_TYPE_JSON) {
+                       ret = fips_test_one_json_file();
+                       json_decref(json_info.json_root);
+               }  else {
+                       ret = fips_test_one_file();
+               }
+#else /* RTE_HAS_JANSSON */
                ret = fips_test_one_file();
+#endif /* RTE_HAS_JANSSON */
+
                if (ret < 0) {
                        RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
                                        ret, env.req_path);
@@ -465,7 +501,17 @@ main(int argc, char *argv[])
                                break;
                        }
 
+#ifdef RTE_HAS_JANSSON
+                       if (info.file_type == FIPS_TYPE_JSON) {
+                               ret = fips_test_one_json_file();
+                               json_decref(json_info.json_root);
+                       } else {
+                               ret = fips_test_one_file();
+                       }
+#else /* RTE_HAS_JANSSON */
                        ret = fips_test_one_file();
+#endif /* RTE_HAS_JANSSON */
+
                        if (ret < 0) {
                                RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n",
                                                ret, req_path);
@@ -483,6 +529,9 @@ exit:
        fips_test_clear();
        cryptodev_fips_validate_app_uninit();
 
+       /* clean up the EAL */
+       rte_eal_cleanup();
+
        return ret;
 
 }
@@ -501,8 +550,7 @@ prepare_data_mbufs(struct fips_val *val)
        uint16_t nb_seg;
        int ret = 0;
 
-       if (env.mbuf)
-               rte_pktmbuf_free(env.mbuf);
+       rte_pktmbuf_free(env.mbuf);
 
        if (total_len > RTE_MBUF_MAX_NB_SEGS) {
                RTE_LOG(ERR, USER1, "Data len %u too big\n", total_len);
@@ -576,8 +624,7 @@ prepare_data_mbufs(struct fips_val *val)
        return 0;
 
 error_exit:
-       if (head)
-               rte_pktmbuf_free(head);
+       rte_pktmbuf_free(head);
        return ret;
 }
 
@@ -634,8 +681,7 @@ prepare_auth_op(void)
        if (ret < 0)
                return ret;
 
-       if (env.digest)
-               rte_free(env.digest);
+       rte_free(env.digest);
 
        env.digest = rte_zmalloc(NULL, vec.cipher_auth.digest.len,
                        RTE_CACHE_LINE_SIZE);
@@ -683,8 +729,7 @@ prepare_aead_op(void)
                if (ret < 0)
                        return ret;
 
-               if (env.digest)
-                       rte_free(env.digest);
+               rte_free(env.digest);
                env.digest = rte_zmalloc(NULL, vec.aead.digest.len,
                                RTE_CACHE_LINE_SIZE);
                if (!env.digest) {
@@ -927,10 +972,14 @@ prepare_gmac_xform(struct rte_crypto_sym_xform *xform)
 
        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",
+                       auth_xform->digest_length,
+                       auth_xform->iv.length) != 0) {
+
+               RTE_LOG(ERR, USER1,
+                       "PMD %s key length %u Digest length %u IV length %u\n",
                                info.device_name, auth_xform->key.length,
-                               auth_xform->digest_length);
+                               auth_xform->digest_length,
+                               auth_xform->iv.length);
                return -EPERM;
        }
 
@@ -1128,6 +1177,7 @@ get_writeback_data(struct fips_val *val)
 
        if (data_len) {
                RTE_LOG(ERR, USER1, "Error -1: write back data\n");
+               free(wb_data);
                return -1;
        }
 
@@ -1199,11 +1249,15 @@ fips_generic_test(void)
        struct fips_val val = {NULL, 0};
        int ret;
 
-       fips_test_write_one_case();
+       if (info.file_type != FIPS_TYPE_JSON)
+               fips_test_write_one_case();
 
        ret = fips_run_test();
        if (ret < 0) {
                if (ret == -EPERM || ret == -ENOTSUP) {
+                       if (info.file_type == FIPS_TYPE_JSON)
+                               return ret;
+
                        fprintf(info.fp_wr, "Bypass\n\n");
                        return 0;
                }
@@ -1218,6 +1272,7 @@ fips_generic_test(void)
        switch (info.file_type) {
        case FIPS_TYPE_REQ:
        case FIPS_TYPE_RSP:
+       case FIPS_TYPE_JSON:
                if (info.parse_writeback == NULL)
                        return -EPERM;
                ret = info.parse_writeback(&val);
@@ -1231,9 +1286,12 @@ fips_generic_test(void)
                if (ret < 0)
                        return ret;
                break;
+       default:
+               break;
        }
 
-       fprintf(info.fp_wr, "\n");
+       if (info.file_type != FIPS_TYPE_JSON)
+               fprintf(info.fp_wr, "\n");
        free(val.val);
 
        return 0;
@@ -1268,6 +1326,9 @@ fips_mct_tdes_test(void)
                        ret = fips_run_test();
                        if (ret < 0) {
                                if (ret == -EPERM) {
+                                       if (info.file_type == FIPS_TYPE_JSON)
+                                               return ret;
+
                                        fprintf(info.fp_wr, "Bypass\n");
                                        return 0;
                                }
@@ -1403,8 +1464,7 @@ fips_mct_tdes_test(void)
                }
        }
 
-       if (val.val)
-               free(val.val);
+       free(val.val);
 
        return 0;
 }
@@ -1430,6 +1490,9 @@ fips_mct_aes_ecb_test(void)
                        ret = fips_run_test();
                        if (ret < 0) {
                                if (ret == -EPERM) {
+                                       if (info.file_type == FIPS_TYPE_JSON)
+                                               return ret;
+
                                        fprintf(info.fp_wr, "Bypass\n");
                                        return 0;
                                }
@@ -1483,8 +1546,7 @@ fips_mct_aes_ecb_test(void)
                }
        }
 
-       if (val.val)
-               free(val.val);
+       free(val.val);
 
        return 0;
 }
@@ -1494,7 +1556,7 @@ fips_mct_aes_test(void)
 #define AES_BLOCK_SIZE 16
 #define AES_EXTERN_ITER        100
 #define AES_INTERN_ITER        1000
-       struct fips_val val = {NULL, 0}, val_key;
+       struct fips_val val[3] = {{NULL, 0},}, val_key,  pt, ct, iv;
        uint8_t prev_out[AES_BLOCK_SIZE] = {0};
        uint8_t prev_in[AES_BLOCK_SIZE] = {0};
        uint32_t i, j, k;
@@ -1503,16 +1565,24 @@ fips_mct_aes_test(void)
        if (info.interim_info.aes_data.cipher_algo == RTE_CRYPTO_CIPHER_AES_ECB)
                return fips_mct_aes_ecb_test();
 
+       memset(&pt, 0, sizeof(struct fips_val));
+       memset(&ct, 0, sizeof(struct fips_val));
+       memset(&iv, 0, sizeof(struct fips_val));
        for (i = 0; i < AES_EXTERN_ITER; i++) {
-               if (i != 0)
-                       update_info_vec(i);
+               if (info.file_type != FIPS_TYPE_JSON) {
+                       if (i != 0)
+                               update_info_vec(i);
 
-               fips_test_write_one_case();
+                       fips_test_write_one_case();
+               }
 
                for (j = 0; j < AES_INTERN_ITER; j++) {
                        ret = fips_run_test();
                        if (ret < 0) {
                                if (ret == -EPERM) {
+                                       if (info.file_type == FIPS_TYPE_JSON)
+                                               return ret;
+
                                        fprintf(info.fp_wr, "Bypass\n");
                                        return 0;
                                }
@@ -1520,7 +1590,7 @@ fips_mct_aes_test(void)
                                return ret;
                        }
 
-                       ret = get_writeback_data(&val);
+                       ret = get_writeback_data(&val[0]);
                        if (ret < 0)
                                return ret;
 
@@ -1528,24 +1598,39 @@ fips_mct_aes_test(void)
                                memcpy(prev_in, vec.ct.val, AES_BLOCK_SIZE);
 
                        if (j == 0) {
-                               memcpy(prev_out, val.val, AES_BLOCK_SIZE);
+                               memcpy(prev_out, val[0].val, AES_BLOCK_SIZE);
+                               pt.len = vec.pt.len;
+                               pt.val = calloc(1, pt.len);
+                               memcpy(pt.val, vec.pt.val, pt.len);
+
+                               ct.len = vec.ct.len;
+                               ct.val = calloc(1, ct.len);
+                               memcpy(ct.val, vec.ct.val, ct.len);
+
+                               iv.len = vec.iv.len;
+                               iv.val = calloc(1, iv.len);
+                               memcpy(iv.val, vec.iv.val, iv.len);
 
                                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);
+                                       memcpy(vec.pt.val, vec.iv.val, AES_BLOCK_SIZE);
+                                       memcpy(vec.iv.val, val[0].val, AES_BLOCK_SIZE);
+                                       val[1].val = pt.val;
+                                       val[1].len = pt.len;
+                                       val[2].val = iv.val;
+                                       val[2].len = iv.len;
                                } else {
-                                       memcpy(vec.ct.val, vec.iv.val,
-                                                       AES_BLOCK_SIZE);
-                                       memcpy(vec.iv.val, prev_in,
-                                                       AES_BLOCK_SIZE);
+                                       memcpy(vec.ct.val, vec.iv.val, AES_BLOCK_SIZE);
+                                       memcpy(vec.iv.val, prev_in, AES_BLOCK_SIZE);
+                                       val[1].val = ct.val;
+                                       val[1].len = ct.len;
+                                       val[2].val = iv.val;
+                                       val[2].len = iv.len;
                                }
                                continue;
                        }
 
                        if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
-                               memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
+                               memcpy(vec.iv.val, val[0].val, AES_BLOCK_SIZE);
                                memcpy(vec.pt.val, prev_out, AES_BLOCK_SIZE);
                        } else {
                                memcpy(vec.iv.val, prev_in, AES_BLOCK_SIZE);
@@ -1555,33 +1640,38 @@ fips_mct_aes_test(void)
                        if (j == AES_INTERN_ITER - 1)
                                continue;
 
-                       memcpy(prev_out, val.val, AES_BLOCK_SIZE);
+                       memcpy(prev_out, val[0].val, AES_BLOCK_SIZE);
                }
 
-               info.parse_writeback(&val);
-               fprintf(info.fp_wr, "\n");
+               info.parse_writeback(val);
+               if (info.file_type != FIPS_TYPE_JSON)
+                       fprintf(info.fp_wr, "\n");
 
-               if (i == AES_EXTERN_ITER - 1)
+               if (i == AES_EXTERN_ITER - 1) {
+                       free(pt.val);
+                       free(ct.val);
+                       free(iv.val);
                        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];
+                               val_key.val[k] ^= val[0].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];
+                                       val_key.val[k] ^= val[0].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];
+                                       val_key.val[k] ^= val[0].val[k - 16];
                                break;
                        default:
                                return -1;
@@ -1589,11 +1679,10 @@ fips_mct_aes_test(void)
                }
 
                if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
-                       memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE);
+                       memcpy(vec.iv.val, val[0].val, AES_BLOCK_SIZE);
        }
 
-       if (val.val)
-               free(val.val);
+       free(val[0].val);
 
        return 0;
 }
@@ -1609,7 +1698,6 @@ fips_mct_sha_test(void)
        int ret;
        uint32_t i, j;
 
-       val.val = rte_malloc(NULL, (MAX_DIGEST_SIZE*SHA_MD_BLOCK), 0);
        for (i = 0; i < SHA_MD_BLOCK; i++)
                md[i].val = rte_malloc(NULL, (MAX_DIGEST_SIZE*2), 0);
 
@@ -1645,6 +1733,9 @@ fips_mct_sha_test(void)
                        ret = fips_run_test();
                        if (ret < 0) {
                                if (ret == -EPERM || ret == -ENOTSUP) {
+                                       if (info.file_type == FIPS_TYPE_JSON)
+                                               return ret;
+
                                        fprintf(info.fp_wr, "Bypass\n\n");
                                        return 0;
                                }
@@ -1680,8 +1771,7 @@ fips_mct_sha_test(void)
 
        rte_free(vec.pt.val);
 
-       if (val.val)
-               free(val.val);
+       free(val.val);
 
        return 0;
 }
@@ -1821,10 +1911,177 @@ error_one_case:
 
        fips_test_clear();
 
-       if (env.digest)
+       if (env.digest) {
                rte_free(env.digest);
-       if (env.mbuf)
-               rte_pktmbuf_free(env.mbuf);
+               env.digest = NULL;
+       }
+       rte_pktmbuf_free(env.mbuf);
+
+       return ret;
+}
+
+#ifdef RTE_HAS_JANSSON
+static int
+fips_test_json_init_writeback(void)
+{
+       json_t *session_info, *session_write;
+       session_info = json_array_get(json_info.json_root, 0);
+       session_write = json_object();
+       json_info.json_write_root = json_array();
+
+       json_object_set(session_write, "jwt",
+               json_object_get(session_info, "jwt"));
+       json_object_set(session_write, "url",
+               json_object_get(session_info, "url"));
+       json_object_set(session_write, "isSample",
+               json_object_get(session_info, "isSample"));
+
+       json_info.is_sample = json_boolean_value(
+               json_object_get(session_info, "isSample"));
+
+       json_array_append_new(json_info.json_write_root, session_write);
+       return 0;
+}
+
+static int
+fips_test_one_test_case(void)
+{
+       int ret;
+
+       ret = fips_test_parse_one_json_case();
 
+       switch (ret) {
+       case 0:
+               ret = test_ops.test();
+               if ((ret == 0) || (ret == -EPERM || ret == -ENOTSUP))
+                       break;
+               RTE_LOG(ERR, USER1, "Error %i: test block\n",
+                               ret);
+               break;
+       default:
+               RTE_LOG(ERR, USER1, "Error %i: Parse block\n",
+                               ret);
+       }
        return ret;
 }
+
+static int
+fips_test_one_test_group(void)
+{
+       int ret;
+       json_t *tests, *write_tests;
+       size_t test_idx, tests_size;
+
+       write_tests = json_array();
+       json_info.json_write_group = json_object();
+       json_object_set(json_info.json_write_group, "tgId",
+               json_object_get(json_info.json_test_group, "tgId"));
+       json_object_set_new(json_info.json_write_group, "tests", write_tests);
+
+       switch (info.algo) {
+       case FIPS_TEST_ALGO_AES_GCM:
+               ret = parse_test_gcm_json_init();
+               break;
+       case FIPS_TEST_ALGO_HMAC:
+               ret = parse_test_hmac_json_init();
+               break;
+       case FIPS_TEST_ALGO_AES_CMAC:
+               ret = parse_test_cmac_json_init();
+               break;
+       case FIPS_TEST_ALGO_AES:
+               ret = parse_test_aes_json_init();
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (ret < 0)
+               return ret;
+
+       ret = fips_test_parse_one_json_group();
+       if (ret < 0)
+               return ret;
+
+       ret = init_test_ops();
+       if (ret < 0)
+               return ret;
+
+       tests = json_object_get(json_info.json_test_group, "tests");
+       tests_size = json_array_size(tests);
+       for (test_idx = 0; test_idx < tests_size; test_idx++) {
+               json_info.json_test_case = json_array_get(tests, test_idx);
+               if (fips_test_one_test_case() == 0)
+                       json_array_append_new(write_tests, json_info.json_write_case);
+       }
+
+       return 0;
+}
+
+static int
+fips_test_one_vector_set(void)
+{
+       int ret;
+       json_t *test_groups, *write_groups, *write_version, *write_set;
+       size_t group_idx, num_groups;
+
+       test_groups = json_object_get(json_info.json_vector_set, "testGroups");
+       num_groups = json_array_size(test_groups);
+
+       json_info.json_write_set = json_array();
+       write_version = json_object();
+       json_object_set_new(write_version, "acvVersion", json_string(ACVVERSION));
+       json_array_append_new(json_info.json_write_set, write_version);
+
+       write_set = json_object();
+       json_array_append(json_info.json_write_set, write_set);
+       write_groups = json_array();
+
+       json_object_set(write_set, "vsId",
+               json_object_get(json_info.json_vector_set, "vsId"));
+       json_object_set(write_set, "algorithm",
+               json_object_get(json_info.json_vector_set, "algorithm"));
+       json_object_set(write_set, "revision",
+               json_object_get(json_info.json_vector_set, "revision"));
+       json_object_set_new(write_set, "isSample",
+               json_boolean(json_info.is_sample));
+       json_object_set_new(write_set, "testGroups", write_groups);
+
+       ret = fips_test_parse_one_json_vector_set();
+       if (ret < 0) {
+               RTE_LOG(ERR, USER1, "Error: Unsupported or invalid vector set algorithm: %s\n",
+                       json_string_value(json_object_get(json_info.json_vector_set, "algorithm")));
+               return ret;
+       }
+
+       for (group_idx = 0; group_idx < num_groups; group_idx++) {
+               json_info.json_test_group = json_array_get(test_groups, group_idx);
+               ret = fips_test_one_test_group();
+               json_array_append_new(write_groups, json_info.json_write_group);
+       }
+
+       return 0;
+}
+
+static int
+fips_test_one_json_file(void)
+{
+       size_t vector_set_idx, root_size;
+
+       root_size = json_array_size(json_info.json_root);
+       fips_test_json_init_writeback();
+
+       for (vector_set_idx = 1; vector_set_idx < root_size; vector_set_idx++) {
+               /* Vector set index starts at 1, the 0th index contains test session
+                * information.
+                */
+               json_info.json_vector_set = json_array_get(json_info.json_root, vector_set_idx);
+               fips_test_one_vector_set();
+               json_array_append_new(json_info.json_write_root, json_info.json_write_set);
+       }
+
+       json_dumpf(json_info.json_write_root, info.fp_wr, JSON_INDENT(4));
+       json_decref(json_info.json_write_root);
+
+       return 0;
+}
+#endif /* RTE_HAS_JANSSON */