From patchwork Fri Sep 7 17:13:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Kovacevic, Marko" X-Patchwork-Id: 44427 X-Patchwork-Delegate: gakhil@marvell.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 7AFF35B1C; Fri, 7 Sep 2018 19:15:33 +0200 (CEST) Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by dpdk.org (Postfix) with ESMTP id 11E124F91 for ; Fri, 7 Sep 2018 19:15:30 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Sep 2018 10:15:29 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.53,343,1531810800"; d="scan'208";a="89848920" Received: from silpixa00399502.ir.intel.com (HELO silpixa00399502.ger.corp.intel.com) ([10.237.223.218]) by orsmga002.jf.intel.com with ESMTP; 07 Sep 2018 10:15:05 -0700 From: Marko Kovacevic To: dev@dpdk.org Cc: akhil.goyal@nxp.com, roy.fan.zhang@intel.com, Marko Kovacevic Date: Fri, 7 Sep 2018 18:13:11 +0100 Message-Id: <20180907171311.20371-3-marko.kovacevic@intel.com> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20180907171311.20371-1-marko.kovacevic@intel.com> References: <20180907171311.20371-1-marko.kovacevic@intel.com> Subject: [dpdk-dev] [PATCH v1 2/2] test/test: cryptodev application parser for FIPS certification X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Added parser to parser required request file which has different algos required by the fips certification and to generate the response file needed. Signed-off-by: Marko Kovacevic --- test/test/Makefile | 3 + test/test/test_cryptodev_fips_parse.h | 156 +++++++++++ test/test/test_cryptodev_fips_parse_aes.c | 399 +++++++++++++++++++++++++++ test/test/test_cryptodev_fips_parse_common.c | 330 ++++++++++++++++++++++ 4 files changed, 888 insertions(+) create mode 100644 test/test/test_cryptodev_fips_parse.h create mode 100644 test/test/test_cryptodev_fips_parse_aes.c create mode 100644 test/test/test_cryptodev_fips_parse_common.c diff --git a/test/test/Makefile b/test/test/Makefile index ee74450..9d6abb5 100644 --- a/test/test/Makefile +++ b/test/test/Makefile @@ -183,6 +183,9 @@ SRCS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += test_cryptodev_blockcipher.c SRCS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += test_cryptodev.c SRCS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += test_cryptodev_asym.c SRCS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += test_cryptodev_fips.c +SRCS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += test_cryptodev_fips_parse_common.c +SRCS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += test_cryptodev_fips_parse_aes.c + ifeq ($(CONFIG_RTE_COMPRESSDEV_TEST),y) SRCS-$(CONFIG_RTE_LIBRTE_COMPRESSDEV) += test_compressdev.c diff --git a/test/test/test_cryptodev_fips_parse.h b/test/test/test_cryptodev_fips_parse.h new file mode 100644 index 0000000..edb1d41 --- /dev/null +++ b/test/test/test_cryptodev_fips_parse.h @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ +#ifndef _TEST_CRYPTODEV_FIPS_PARSE_ +#define _TEST_CRYPTODEV_FIPS_PARSE_ + +#include + +#define FIPS_PARSE_ERR(line, fmt, args...) \ + RTE_LOG(ERR, USER1, "[%s] %s() line %u: Error in file line %u " \ + fmt "\n", "FIPS", __func__, __LINE__, line, ## args) + +#define ERR_MSG_SIZE 128 +#define MAX_CASE_LINE 15 +#define MAX_NB_CHAR 1024 /*< maximum number of characters per line */ +#define MAX_NB_TESTS 10240 +#define MAX_BUF_SIZE 2048 /*< maximum plain/cipher text size */ +#define MAX_KEY_LEN 64 +#define MAX_IV_LEN 256 + +#define POSITIVE_TEST 0 +#define NEGATIVE_TEST -1 + +#define REQ_FILE_PERFIX "req" +#define RSP_FILE_PERFIX "rsp" +#define FAX_FILE_PERFIX "fax" + +#define HEADER_IND "#" +#define GEN_TIME_STR "# Generated on " + +enum file_types { + FIPS_FILE_TYPE_REQ = 1, + FIPS_FILE_TYPE_FAX, + FIPS_FILE_TYPE_RSP +}; + +struct fips_aes_test_case { + char case_desc[MAX_CASE_LINE][MAX_NB_CHAR]; +#define AESAVS_OP_ENC 1 +#define AESAVS_OP_DEC 2 + enum rte_crypto_cipher_operation test_op; + uint8_t key[MAX_KEY_LEN]; + uint8_t iv[MAX_IV_LEN]; + uint32_t iv_len; + uint8_t plaintext[MAX_BUF_SIZE]; + uint32_t plaintext_len; + uint8_t ciphertext[MAX_BUF_SIZE]; + uint32_t ciphertext_len; + uint32_t count; + uint32_t skip_flag; +}; + +/* AES TEST DATA */ +struct fips_aes_test_data { + enum file_types f_type; + char file_header[MAX_CASE_LINE][MAX_NB_CHAR]; + +/* follow the sequence as test_type_strings declared above */ +#define AESAVS_TYPE_GFXBOX 0 +#define AESAVS_TYPE_KEYSBOX 1 +#define AESAVS_TYPE_VARKEY 2 +#define AESAVS_TYPE_VARTXT 3 +#define AESAVS_TYPE_MMT 4 +#define AESAVS_TYPE_MCT 5 + uint32_t test_type; + + /* *_algo == 0 means no algo */ + enum rte_crypto_cipher_algorithm cipher_algo; + enum rte_crypto_auth_algorithm auth_algo; + + uint32_t key_len; + + uint32_t nb_test_cases; + + struct fips_aes_test_case test_cases[MAX_NB_TESTS]; +}; + +/** + * INTERNAL APIS, used for other parsers + */ +int +fips_get_file_line(FILE **fp, char *line, uint32_t max_line_char); + +int +parser_read_uint64(uint64_t *value, const char *p); + +int +parser_read_uint64_hex(uint64_t *value, const char *p); + +int +parser_read_uint32(uint32_t *value, const char *p); + +int +parser_read_uint32_hex(uint32_t *value, const char *p); + +int +parser_read_uint16(uint16_t *value, const char *p); + +int +parser_read_uint16_hex(uint16_t *value, const char *p); + +int +parser_read_uint8(uint8_t *value, const char *p); + +int +parser_read_uint8_hex(uint8_t *value, const char *p); + +int +parse_uint8_hex_str(uint8_t *dst, char *src, uint32_t max_len); + +enum file_types +parse_file_type(const char *path); + +int +fetch_block(FILE **fp, char *line[MAX_CASE_LINE], uint32_t from_line, + const char *trigger, uint32_t max_nb_line_char); + +void +copy_block(char dst[][MAX_NB_CHAR], char *src[MAX_CASE_LINE], + uint32_t nb_lines, uint32_t max_nb_line_char); + +void +write_block_to_file(FILE *fp, char from[][MAX_NB_CHAR]); + +void +write_uint8_str_to_file(FILE *fp, const uint8_t *from, uint32_t size); + +int +alloc_line_block_mem(char *block[MAX_CASE_LINE], uint32_t max_nb_line_char); + +void +free_line_block_mem(char *block[MAX_CASE_LINE]); + +static inline void +MEMSET_BLOCK(char *line[], uint32_t line_len) +{ + uint32_t i; + + for (i = 0; i < MAX_CASE_LINE; i++) + memset(line[i], 0, line_len); +} + + +/** + * API to parse one AES FIPS test vector file into struct FIPS_aes_test_data + * No init is necessary, this function will memset it for you + * No fopen/fclose necessary + */ +int +parse_aes_vectors(struct fips_aes_test_data *aes_test_data, const char *path); + +int +write_aes_vectors(struct fips_aes_test_data *test_data, + const char *path_write, const char *device_name); + +#endif diff --git a/test/test/test_cryptodev_fips_parse_aes.c b/test/test/test_cryptodev_fips_parse_aes.c new file mode 100644 index 0000000..552a493 --- /dev/null +++ b/test/test/test_cryptodev_fips_parse_aes.c @@ -0,0 +1,399 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#include +#include + +#include "test_cryptodev_fips_parse.h" + +#define MODE_STR "AESVS" +#define ALGO_STR "test data for " +#define OP_STR "State" +#define KEY_SIZE_STR "Key Length : " +#define DEVICE_STR "# Config info for " + +#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" + +#define SKIP_OUTPUT "FAIL(Not supported)" + +const char *aes_test_type_strings[] = { + "GFSbox", + "KeySbox", + "VarKey", + "VarTxt", + "MMT", + "MCT" +}; + +struct aes_test_algo_conv { + const char *name; + enum rte_crypto_cipher_algorithm algo; +} const algo_convs[] = { + {"CBC", RTE_CRYPTO_CIPHER_AES_CBC}, +}; + +static int +parse_one_case(struct fips_aes_test_data *test_data, char *lines[], + uint32_t nb_lines, enum rte_crypto_cipher_operation op, + uint32_t from_line) +{ + struct fips_aes_test_case *test_case; + uint32_t i; + char *tmp; + int ret; + + if (test_data->nb_test_cases >= MAX_NB_TESTS) + return -ENOMEM; + + test_case = &test_data->test_cases[test_data->nb_test_cases]; + test_case->test_op = op; + + for (i = 0; i < nb_lines; i++) { + char *line = lines[i]; + + tmp = strstr(line, COUNT_STR); + if (tmp) { + uint32_t count; + + tmp += strlen(COUNT_STR); + if (parser_read_uint32(&count, tmp) < 0) { + ret = -EINVAL; + goto error_exit; + } + + test_case->count = count; + continue; + } + + /* key */ + tmp = strstr(line, KEY_STR); + if (tmp) { + tmp += strlen(KEY_STR); + ret = parse_uint8_hex_str(test_case->key, tmp, MAX_KEY_LEN); + if (ret < 0) + goto error_exit; + continue; + } + + /* iv */ + tmp = strstr(line, IV_STR); + if (tmp) { + tmp += strlen(IV_STR); + + ret = parse_uint8_hex_str(test_case->iv, tmp, MAX_IV_LEN); + if (ret < 0) + goto error_exit; + + test_case->iv_len = ret; + continue; + } + + /* plaintext */ + tmp = strstr(line, PT_STR); + if (tmp) { + tmp += strlen(PT_STR); + + ret = parse_uint8_hex_str(test_case->plaintext, tmp, + MAX_BUF_SIZE); + if (ret < 0) + goto error_exit; + + test_case->plaintext_len = ret; + continue; + } + + /* ciphertext */ + tmp = strstr(line, CT_STR); + if (tmp) { + tmp += strlen(CT_STR); + + ret = parse_uint8_hex_str(test_case->ciphertext, tmp, + MAX_BUF_SIZE); + if (ret < 0) + goto error_exit; + + test_case->ciphertext_len = ret; + continue; + } + } + + copy_block(test_case->case_desc, lines, nb_lines, MAX_NB_CHAR); + test_data->nb_test_cases++; + return 0; + +error_exit: + FIPS_PARSE_ERR(from_line + i, "Error code %i", ret); + memset(test_case, 0, sizeof(*test_case)); + return ret; +} + +static int +parse_header(struct fips_aes_test_data *test_data, char *lines[], + uint32_t nb_lines) +{ + char *tmp; + uint32_t i, j; + + for (i = 0; i < nb_lines; i++) { + char *line = lines[i]; + + tmp = strstr(line, MODE_STR); + if (tmp) { + for (j = 0; j < RTE_DIM(aes_test_type_strings); j++) + if (strstr(line, aes_test_type_strings[j]) + != NULL) { + test_data->test_type = j; + break; + } + if (j >= RTE_DIM(aes_test_type_strings)) + return -EINVAL; + + tmp = strstr(line, ALGO_STR); + if (!tmp) + return -EINVAL; + + tmp += strlen(ALGO_STR); + for (j = 0; j < RTE_DIM(algo_convs); j++) + if (strcmp(algo_convs[j].name, tmp) == 0) { + test_data->cipher_algo = + algo_convs[j].algo; + break; + } + if (j >= RTE_DIM(algo_convs)) + return -EINVAL; + + continue; + } + + /* State : {and } Encrypt and Decrypt, we don't care*/ + tmp = strstr(line, OP_STR); + if (tmp) + continue; + + /* Key Length : 128 */ + tmp = strstr(line, KEY_SIZE_STR); + if (tmp) { + tmp += strlen(KEY_SIZE_STR); + if (parser_read_uint32(&test_data->key_len, tmp) < 0) + return -EINVAL; + + test_data->key_len /= 8; + if (test_data->key_len > MAX_KEY_LEN) + return -EINVAL; + + continue; + } + } + + return 0; +} + +int +parse_aes_vectors(struct fips_aes_test_data *test_data, const char *path) +{ + FILE *fp; + char *line[MAX_CASE_LINE]; + uint32_t line_idx = 0; + enum rte_crypto_cipher_operation op = RTE_CRYPTO_CIPHER_OP_ENCRYPT; + int ret = 0, file_ret = 0; + char *tmp; + + fp = fopen(path, "r"); + if (fp == NULL) { + FIPS_PARSE_ERR(0, "Cannot open file %s", path); + return -EINVAL; + } + + if ((ret = alloc_line_block_mem(line, MAX_NB_CHAR)) < 0) + goto error_exit; + + memset(test_data, 0, sizeof(*test_data)); + + test_data->f_type = parse_file_type(path); + if (test_data->f_type == 0) { + FIPS_PARSE_ERR(0, "Cannot get file type %s", path); + goto error_exit; + } + + while (file_ret != -EOF) { + line_idx++; + + file_ret = fips_get_file_line(&fp, line[0], MAX_NB_CHAR); + if (file_ret < 0) { + FIPS_PARSE_ERR(line_idx, "Error code %i", ret); + ret = file_ret; + goto error_exit; + } + + ret = fetch_block(&fp, line, line_idx, HEADER_IND, MAX_NB_CHAR); + if (ret <= 0) { + ret = -EINVAL; + goto error_exit; + } + + copy_block(test_data->file_header, line, ret, MAX_NB_CHAR); + + ret = parse_header(test_data, line, ret); + if (ret < 0) + goto error_exit; + break; + } + + MEMSET_BLOCK(line, MAX_NB_CHAR); + + while (file_ret != -EOF) { + line_idx++; + + file_ret = fips_get_file_line(&fp, line[0], MAX_NB_CHAR); + if (file_ret < 0) { + FIPS_PARSE_ERR(line_idx, "Error code %i", ret); + ret = file_ret; + goto error_exit; + } + + if (strlen(line[0]) == 0) + continue; + + tmp = strstr(line[0], OP_ENC_STR); + if (tmp) { + op = RTE_CRYPTO_CIPHER_OP_ENCRYPT; + continue; + } + + tmp = strstr(line[0], OP_DEC_STR); + if (tmp) { + op = RTE_CRYPTO_CIPHER_OP_DECRYPT; + continue; + } + + ret = fetch_block(&fp, line, line_idx, COUNT_STR, MAX_NB_CHAR); + if (ret > 0) { + uint32_t start_line = line_idx; + + line_idx += ret; + ret = parse_one_case(test_data, line, ret, op, + start_line); + + MEMSET_BLOCK(line, MAX_NB_CHAR); + } + if (ret < 0) + goto error_exit; + + } + + free_line_block_mem(line); + if (fp) + fclose(fp); + + return 0; +error_exit: + free_line_block_mem(line); + if (fp) + fclose(fp); + return ret; +} + +int +write_aes_vectors(struct fips_aes_test_data *test_data, + const char *path_write, const char *device_name) +{ + FILE *fp; + uint32_t i; + enum rte_crypto_cipher_operation op = 0xf; + time_t t = time(NULL); + struct tm *tm_now = localtime(&t); + + if (test_data->f_type != FIPS_FILE_TYPE_REQ) { + FIPS_PARSE_ERR(0, "Write only works for REQ test vectors"); + return 0; + } + + fp = fopen(path_write, "w"); + if (fp == NULL) { + FIPS_PARSE_ERR(0, "Cannot open file %s", path_write); + return -EINVAL; + } + + /* write back header */ + for (i = 0; i < MAX_CASE_LINE; i++) { + char *line = test_data->file_header[i]; + + if (strlen(line) == 0) + break; + + if (strstr(line, DEVICE_STR)) { + fprintf(fp, "%s%s\n", DEVICE_STR, device_name); + continue; + } + + if (strstr(line, GEN_TIME_STR)) { + fprintf(fp, "%s%s\n", GEN_TIME_STR, asctime(tm_now)); + continue; + } + + fprintf(fp, "%s\n", line); + } + + /* write back test case */ + for (i = 0; i < test_data->nb_test_cases; i++) { + struct fips_aes_test_case *tc = &test_data->test_cases[i]; + + if (op != tc->test_op) { + fprintf(fp, "%s\n\n", tc->test_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT ? + "[ENCRYPT]" : "[DECRYPT]"); + op = tc->test_op; + } + + if (tc->skip_flag) + continue; + + if (test_data->test_type == AESAVS_TYPE_MCT) { + fprintf(fp, "%s%u\n", COUNT_STR, tc->count); + fprintf(fp, "%s", KEY_STR); + write_uint8_str_to_file(fp, tc->key, test_data->key_len); + fprintf(fp, "%s", IV_STR); + write_uint8_str_to_file(fp, tc->iv, tc->iv_len); + if (tc->test_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT) { + fprintf(fp, "%s", PT_STR); + write_uint8_str_to_file(fp, tc->plaintext, + tc->plaintext_len); + fprintf(fp, "%s", CT_STR); + write_uint8_str_to_file(fp, tc->ciphertext, + tc->ciphertext_len); + } else { + fprintf(fp, "%s", CT_STR); + write_uint8_str_to_file(fp, tc->ciphertext, + tc->ciphertext_len); + fprintf(fp, "%s", PT_STR); + write_uint8_str_to_file(fp, tc->plaintext, + tc->plaintext_len); + } + } else { + write_block_to_file(fp, tc->case_desc); + + if (tc->test_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT) { + fprintf(fp, "%s", CT_STR); + write_uint8_str_to_file(fp, tc->ciphertext, + tc->ciphertext_len); + } else { + fprintf(fp, "%s", PT_STR); + write_uint8_str_to_file(fp, tc->plaintext, + tc->plaintext_len); + } + } + + fprintf(fp, "\n"); + } + + fclose(fp); + + return 0; +} diff --git a/test/test/test_cryptodev_fips_parse_common.c b/test/test/test_cryptodev_fips_parse_common.c new file mode 100644 index 0000000..1caa755 --- /dev/null +++ b/test/test/test_cryptodev_fips_parse_common.c @@ -0,0 +1,330 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ +#include +#include + +#include + +#include "test_cryptodev_fips_parse.h" + +/* + * copy a line in the file to the buffer + * if EOF, return -EOF + * otherwise return 0 + */ +int +fips_get_file_line(FILE **fp, char *line, uint32_t max_line_char) +{ + 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; + } + + return -EOF; +} + +#define skip_white_spaces(pos) \ +({ \ + __typeof__(pos) _p = (pos); \ + for ( ; isspace(*_p); _p++) \ + ; \ + _p; \ +}) + +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_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_uint32(uint32_t *value, const 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; +} + +int +parser_read_uint32_hex(uint32_t *value, const char *p) +{ + uint64_t val = 0; + int ret = parser_read_uint64_hex(&val, p); + + if (ret < 0) + return ret; + + if (val > UINT32_MAX) + return -EINVAL; + + *value = val; + return 0; +} + +int +parser_read_uint16(uint16_t *value, const char *p) +{ + uint64_t val = 0; + int ret = parser_read_uint64(&val, p); + + if (ret < 0) + return ret; + + if (val > UINT16_MAX) + return -EINVAL; + + *value = val; + return 0; +} + +int +parser_read_uint16_hex(uint16_t *value, const char *p) +{ + uint64_t val = 0; + int ret = parser_read_uint64_hex(&val, p); + + if (ret < 0) + return ret; + + if (val > UINT16_MAX) + return -EINVAL; + + *value = val; + return 0; +} + +int +parser_read_uint8(uint8_t *value, const char *p) +{ + uint64_t val = 0; + int ret = parser_read_uint64(&val, p); + + if (ret < 0) + return ret; + + if (val > UINT8_MAX) + 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 -EINVAL; + + *value = val; + return 0; +} + +int +parse_uint8_hex_str(uint8_t *dst, char *src, uint32_t max_len) +{ + uint32_t len, j; + + len = strlen(src) / 2; + if (len > max_len) + return -ENOMEM; + + for (j = 0; j < len; j++) { + char byte[3] = {src[j * 2], src[j * 2 + 1], '\0'}; + + if (parser_read_uint8_hex(&dst[j], byte) < 0) + return -EINVAL; + } + + return len; +} + +enum file_types +parse_file_type(const char *path) +{ + const char *tmp = path + strlen(path) - 3; + + if (strstr(tmp, REQ_FILE_PERFIX)) + return FIPS_FILE_TYPE_REQ; + else if (strstr(tmp, RSP_FILE_PERFIX)) + return FIPS_FILE_TYPE_RSP; + else if (strstr(path, FAX_FILE_PERFIX)) + return FIPS_FILE_TYPE_FAX; + + return 0; +} + +/* copy block text from file, stop on line with size of 0 or EOF, max + * MAX_CASE_LINE lines */ +int +fetch_block(FILE **fp, char *line[MAX_CASE_LINE], uint32_t from_line, + const char *trigger, uint32_t max_nb_line_char) +{ + uint32_t i = 1; + int ret = 0; + + if (strstr(line[0], trigger) == NULL) + return 0; + + while (i < MAX_CASE_LINE && ret != -EOF) { + ret = fips_get_file_line(fp, line[i], max_nb_line_char); + if (ret < 0) { + FIPS_PARSE_ERR(from_line + i, "Error code %i", ret); + return ret; + } + + if (ret == -EOF || strlen(line[i]) == 0) + break; + + i++; + } + + return i; +} + +void +copy_block(char dst[][MAX_NB_CHAR], char *src[MAX_CASE_LINE], + uint32_t nb_lines, uint32_t max_nb_line_char) +{ + uint32_t i; + + for (i = 0; i < nb_lines; i++) + memcpy(dst[i], src[i], max_nb_line_char - 1); +} + +void +write_block_to_file(FILE *fp, char from[][MAX_NB_CHAR]) +{ + uint32_t i; + + for (i = 0; i < MAX_CASE_LINE; i++) { + if (from[i] == NULL) + break; + if (strlen(from[i]) == 0) + break; + fprintf(fp, "%s\n", from[i]); + } +} + +void +write_uint8_str_to_file(FILE *fp, const uint8_t *from, uint32_t size) +{ + uint32_t i; + + for (i = 0; i < size; i++) + fprintf(fp, "%02x", from[i]); + + fprintf(fp, "\n"); +} + +int +alloc_line_block_mem(char *block[MAX_CASE_LINE], uint32_t max_nb_line_char) +{ + uint32_t i; + + for (i = 0; i < MAX_CASE_LINE; i++) + block[i] = NULL; + + for (i = 0; i < MAX_CASE_LINE; i++) { + block[i] = malloc(max_nb_line_char); + if (!block[i]) + goto error_exit; + } + + return 0; + +error_exit: + for (i = 0; i < MAX_CASE_LINE; i++) + if (block[i]) + free(block[i]); + + return -ENOMEM; +} + +void +free_line_block_mem(char *block[MAX_CASE_LINE]) +{ + uint32_t i; + + for (i = 0; i < MAX_CASE_LINE; i++) + if (block[i]) + free(block[i]); +}