[v1,2/2] test/test: cryptodev application parser for FIPS certification
diff mbox series

Message ID 20180907171311.20371-3-marko.kovacevic@intel.com
State Superseded, archived
Delegated to: akhil goyal
Headers show
Series
  • FIPS validation capability
Related show

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/Intel-compilation success Compilation OK

Commit Message

Kovacevic, Marko Sept. 7, 2018, 5:13 p.m. UTC
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 <marko.kovacevic@intel.com>
---
 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

Patch
diff mbox series

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 <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
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 <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;
+}
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 <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]);
+}