@@ -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
new file mode 100644
@@ -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 <rte_cryptodev.h>
+
+#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
new file mode 100644
@@ -0,0 +1,399 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <time.h>
+
+#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 : <op> {and <op>} 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;
+}
new file mode 100644
@@ -0,0 +1,330 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+#include <string.h>
+#include <stdio.h>
+
+#include <rte_cryptodev.h>
+
+#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]);
+}