[dpdk-dev] [PATCH v2 4/8] examples: add TDES parser and enablement for test types

Fan Zhang roy.fan.zhang at intel.com
Thu Oct 4 11:40:11 CEST 2018


From: Marko Kovacevic <marko.kovacevic at intel.com>

Added enablement for TDES parser, to allow the
application to parser the TDES request files and to validate all
test types supported.

Signed-off-by: Marko Kovacevic <marko.kovacevic at intel.com>
Signed-off-by: Fan Zhang <roy.fan.zhang at intel.com>
---
 examples/cryptodev_fips_validate/Makefile          |   1 +
 .../cryptodev_fips_parse_3des.c                    | 259 +++++++++++++++++++++
 .../cryptodev_fips_parse_aes.c                     |   2 +
 .../cryptodev_fips_parse_validate.c                |   5 +
 .../cryptodev_fips_validate.h                      |  21 ++
 examples/cryptodev_fips_validate/main.c            | 175 ++++++++++++++
 examples/cryptodev_fips_validate/meson.build       |   1 +
 7 files changed, 464 insertions(+)
 create mode 100644 examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c

diff --git a/examples/cryptodev_fips_validate/Makefile b/examples/cryptodev_fips_validate/Makefile
index 50be23cf5..54ea43ffd 100644
--- a/examples/cryptodev_fips_validate/Makefile
+++ b/examples/cryptodev_fips_validate/Makefile
@@ -7,6 +7,7 @@ APP = cryptodev_fips_validate_app
 # all source are stored in SRCS-y
 SRCS-y := cryptodev_fips_parse_aes.c
 SRCS-y += cryptodev_fips_parse_hmac.c
+SRCS-y += cryptodev_fips_parse_3des.c
 SRCS-y += cryptodev_fips_parse_validate.c
 SRCS-y += main.c
 
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c
new file mode 100644
index 000000000..82e9132a7
--- /dev/null
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_3des.c
@@ -0,0 +1,259 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include <rte_malloc.h>
+#include <rte_cryptodev.h>
+
+#include "cryptodev_fips_validate.h"
+
+#define NEW_LINE_STR	"#"
+#define TEST_TYPE_KEY	" for CBC"
+#define TEST_CBCI_KEY	" for CBCI"
+
+#define ENC_STR		"[ENCRYPT]"
+#define DEC_STR		"[DECRYPT]"
+
+#define COUNT_STR	"COUNT = "
+#define KEY1_STR	"KEY1 = "
+#define KEY2_STR	"KEY2 = "
+#define KEY3_STR	"KEY3 = "
+
+#define KEYS_STR	"KEYs = "
+#define IV_STR		"IV = "
+#define PT_STR		"PLAINTEXT = "
+#define CT_STR		"CIPHERTEXT = "
+#define NK_STR		"NumKeys = "
+
+#define SET_STR		" = "
+
+#define PLAIN_TEXT	0
+#define CIPHER_TEXT	1
+#define KEY_TEXT	2
+#define IV_TEXT		3
+
+#define DEVICE_STR	"# Config Info for : "
+
+struct {
+	uint32_t type;
+	const char *desc;
+} test_types[] = {
+		{TDES_INVERSE_PERMUTATION, "INVERSE PERMUTATION"},
+		{TDES_PERMUTATION, "PERMUTATION OPERATION"},
+		{TDES_SUBSTITUTION_TABLE, "SUBSTITUTION TABLE"},
+		{TDES_VARIABLE_KEY, "VARIABLE KEY"},
+		{TDES_VARIABLE_TEXT, "VARIABLE PLAINTEXT/CIPHERTEXT"},
+		{TDES_VARIABLE_TEXT, "KAT"},
+		{TDES_MCT, "Monte Carlo (Modes) Test"},
+		{TDES_MMT, "Multi block Message Test"},
+};
+
+static int
+writeback_tdes_hex_str(const char *key, char *dst, struct fips_val *val);
+
+static int
+parse_3des_uint8_hex_str(const char *key, char *src, struct fips_val *val);
+
+static int
+parse_tdes_interim(const char *key,
+		__attribute__((__unused__)) char *text,
+		struct fips_val *val);
+
+struct fips_test_callback tdes_tests_vectors[] = {
+		{KEYS_STR, parse_3des_uint8_hex_str, &vec.cipher_auth.key},
+		{KEY1_STR, parse_3des_uint8_hex_str, &vec.cipher_auth.key},
+		{KEY2_STR, parse_3des_uint8_hex_str, &vec.cipher_auth.key},
+		{KEY3_STR, parse_3des_uint8_hex_str, &vec.cipher_auth.key},
+		{IV_STR, parse_uint8_hex_str, &vec.iv},
+		{PT_STR, parse_uint8_hex_str, &vec.pt},
+		{CT_STR, parse_uint8_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback tdes_tests_interim_vectors[] = {
+		{ENC_STR, parse_tdes_interim, NULL},
+		{DEC_STR, parse_tdes_interim, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback tdes_writeback_callbacks[] = {
+		/** First element is used to pass COUNT string */
+		{COUNT_STR, NULL, NULL},
+		{IV_STR, writeback_hex_str, &vec.iv},
+		{KEY1_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
+		{KEY2_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
+		{KEY3_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
+		{KEYS_STR, writeback_tdes_hex_str, &vec.cipher_auth.key},
+		{PT_STR, writeback_hex_str, &vec.pt},
+		{CT_STR, writeback_hex_str, &vec.ct},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+static int
+parse_tdes_interim(const char *key,
+		__attribute__((__unused__)) char *text,
+		__attribute__((__unused__)) struct fips_val *val)
+{
+	if (strstr(key, ENC_STR))
+		info.op = FIPS_TEST_ENC_AUTH_GEN;
+	else if (strstr(key, DEC_STR))
+		info.op = FIPS_TEST_DEC_AUTH_VERIF;
+	else if (strstr(NK_STR, "NumKeys = 1"))
+		info.interim_info.tdes_data.nb_keys = 1;
+	else if (strstr(NK_STR, "NumKeys = 2"))
+		info.interim_info.tdes_data.nb_keys = 2;
+	else if (strstr(NK_STR, "NumKeys = 3"))
+		info.interim_info.tdes_data.nb_keys = 3;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int
+parse_3des_uint8_hex_str(const char *key, char *src, struct fips_val *val)
+{
+	uint8_t tmp_key[24] = {0};
+	uint32_t len, i;
+
+	src += strlen(key);
+
+	len = strlen(src) / 2;
+
+	if (val->val) {
+		memcpy(tmp_key, val->val, val->len);
+		rte_free(val->val);
+	}
+
+	val->val = rte_zmalloc(NULL, 24, 0);
+	if (!val->val)
+		return -1;
+
+	memcpy(val->val, tmp_key, 24);
+
+	if (strstr(key, KEYS_STR)) {
+		for (i = 0; i < len; i++) {
+			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
+
+			if (parser_read_uint8_hex(&val->val[i], byte) < 0)
+				return -EINVAL;
+		}
+
+		memcpy(val->val + 8, val->val, 8);
+		memcpy(val->val + 16, val->val, 8);
+
+	} else if (strstr(key, KEY1_STR)) {
+		for (i = 0; i < len; i++) {
+			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
+
+			if (parser_read_uint8_hex(&val->val[i], byte) < 0)
+				return -EINVAL;
+		}
+
+		if (info.interim_info.tdes_data.nb_keys == 2)
+			memcpy(val->val + 16, val->val, 8);
+
+	} else if (strstr(key, KEY2_STR)) {
+		for (i = 0; i < len; i++) {
+			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
+
+			if (parser_read_uint8_hex(&val->val[i + 8], byte) < 0)
+				return -EINVAL;
+		}
+
+	} else if (strstr(key, KEY3_STR)) {
+		for (i = 0; i < len; i++) {
+			char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'};
+
+			if (parser_read_uint8_hex(&val->val[i + 16], byte) < 0)
+				return -EINVAL;
+		}
+	} else
+		return -EINVAL;
+
+	val->len = 24;
+
+	return 0;
+}
+
+static int
+parse_test_tdes_writeback(struct fips_val *val)
+{
+
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN)
+		fprintf(info.fp_wr, "%s", CT_STR);
+	else
+		fprintf(info.fp_wr, "%s", PT_STR);
+
+	parse_write_hex_str(val);
+
+	return 0;
+
+}
+
+static int
+writeback_tdes_hex_str(const char *key, char *dst, struct fips_val *val)
+{
+	struct fips_val tmp_val;
+
+	tmp_val.len = 8;
+
+	if (strstr(key, KEY1_STR))
+		tmp_val.val = val->val;
+	else if (strstr(key, KEY2_STR))
+		tmp_val.val = val->val + 8;
+	else if (strstr(key, KEY3_STR))
+		tmp_val.val = val->val + 16;
+
+	return writeback_hex_str(key, dst, &tmp_val);
+}
+
+static int
+rsp_test_tdes_check(struct fips_val *val)
+{
+	struct fips_val *data;
+
+	if (info.op == FIPS_TEST_ENC_AUTH_GEN)
+		data = &vec.ct;
+	else
+		data = &vec.pt;
+
+	if (memcmp(val->val, data->val, val->len) == 0)
+		fprintf(info.fp_wr, "Success\n");
+	else
+		fprintf(info.fp_wr, "Failed\n");
+
+	return 0;
+}
+
+int
+parse_test_tdes_init(void)
+{
+	uint32_t i;
+
+	for (i = 0; i < info.nb_vec_lines; i++) {
+		char *line = info.vec[i];
+		uint32_t j;
+
+		if (strstr(line, TEST_CBCI_KEY))
+			return -EPERM;
+
+		for (j = 0; j < RTE_DIM(test_types); j++)
+			if (strstr(line, test_types[j].desc)) {
+				info.interim_info.tdes_data.test_type =
+						test_types[j].type;
+				break;
+			}
+	}
+
+	info.parse_writeback = parse_test_tdes_writeback;
+	info.callbacks = tdes_tests_vectors;
+	info.interim_callbacks = tdes_tests_interim_vectors;
+	info.writeback_callbacks = tdes_writeback_callbacks;
+	info.kat_check = rsp_test_tdes_check;
+
+	return 0;
+}
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c
index 39dbd6ff9..cc2775428 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_aes.c
@@ -33,6 +33,8 @@ struct {
 		{AESAVS_TYPE_KEYSBOX, "KeySbox"},
 		{AESAVS_TYPE_VARKEY, "VarKey"},
 		{AESAVS_TYPE_VARTXT, "VarTxt"},
+		{TDES_VARIABLE_TEXT, "VARIABLE PLAINTEXT/CIPHERTEXT"},
+		{TDES_VARIABLE_TEXT, "KAT"},
 		{AESAVS_TYPE_MMT, "MMT"},
 		{AESAVS_TYPE_MCT, "MCT"},
 };
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
index f1cd80253..bb396e54d 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_parse_validate.c
@@ -114,6 +114,11 @@ fips_test_parse_header(void)
 			ret = parse_test_hmac_init();
 			if (ret < 0)
 				return ret;
+		} else if (strstr(info.vec[i], "TDES")) {
+			info.algo = FIPS_TEST_ALGO_TDES;
+			ret = parse_test_tdes_init();
+			if (ret < 0)
+				return 0;
 		}
 
 		tmp = strstr(info.vec[i], "# Config info for ");
diff --git a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
index 3cda9fe87..c9b11dda2 100644
--- a/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
+++ b/examples/cryptodev_fips_validate/cryptodev_fips_validate.h
@@ -25,6 +25,7 @@
 enum fips_test_algorithms {
 		FIPS_TEST_ALGO_AES = 0,
 		FIPS_TEST_ALGO_HMAC,
+		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_MAX
 };
 
@@ -88,6 +89,17 @@ enum fips_aesavs_test_types {
 	AESAVS_TYPE_MCT,
 };
 
+enum fips_tdes_test_types {
+	TDES_INVERSE_PERMUTATION = 0,
+	TDES_PERMUTATION,
+	TDES_SUBSTITUTION_TABLE,
+	TDES_VARIABLE_KEY,
+	TDES_VARIABLE_TEXT,
+	TDES_KAT,
+	TDES_MCT, /* Monte Carlo (Modes) Test */
+	TDES_MMT /* Multi block Message Test */
+};
+
 struct aesavs_interim_data {
 	enum fips_aesavs_test_types test_type;
 	uint32_t cipher_algo;
@@ -98,6 +110,11 @@ struct hmac_interim_data {
 	enum rte_crypto_auth_algorithm algo;
 };
 
+struct tdes_interim_data {
+	enum fips_tdes_test_types test_type;
+	uint32_t nb_keys;
+};
+
 struct fips_test_interim_info {
 	FILE *fp_rd;
 	FILE *fp_wr;
@@ -112,6 +129,7 @@ struct fips_test_interim_info {
 	union {
 		struct aesavs_interim_data aes_data;
 		struct hmac_interim_data hmac_data;
+		struct tdes_interim_data tdes_data;
 
 	} interim_info;
 
@@ -148,6 +166,9 @@ int
 parse_test_aes_init(void);
 
 int
+parse_test_tdes_init(void);
+
+int
 parse_test_hmac_init(void);
 
 int
diff --git a/examples/cryptodev_fips_validate/main.c b/examples/cryptodev_fips_validate/main.c
index cb102a920..8a9622f02 100644
--- a/examples/cryptodev_fips_validate/main.c
+++ b/examples/cryptodev_fips_validate/main.c
@@ -501,6 +501,46 @@ prepare_aes_xform(struct rte_crypto_sym_xform *xform)
 }
 
 static int
+prepare_tdes_xform(struct rte_crypto_sym_xform *xform)
+{
+	const struct rte_cryptodev_symmetric_capability *cap;
+	struct rte_cryptodev_sym_capability_idx cap_idx;
+	struct rte_crypto_cipher_xform *cipher_xform = &xform->cipher;
+
+	xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+
+	cipher_xform->algo = RTE_CRYPTO_CIPHER_3DES_CBC;
+	cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+			RTE_CRYPTO_CIPHER_OP_ENCRYPT :
+			RTE_CRYPTO_CIPHER_OP_DECRYPT;
+	cipher_xform->key.data = vec.cipher_auth.key.val;
+	cipher_xform->key.length = vec.cipher_auth.key.len;
+	cipher_xform->iv.length = vec.iv.len;
+	cipher_xform->iv.offset = IV_OFF;
+
+	cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_3DES_CBC;
+	cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+
+	cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
+	if (!cap) {
+		RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
+				env.dev_id);
+		return -EINVAL;
+	}
+
+	if (rte_cryptodev_sym_capability_check_cipher(cap,
+			cipher_xform->key.length,
+			cipher_xform->iv.length) != 0) {
+		RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
+				info.device_name, cipher_xform->key.length,
+				cipher_xform->iv.length);
+		return -EPERM;
+	}
+
+	return 0;
+}
+
+static int
 prepare_hmac_xform(struct rte_crypto_sym_xform *xform)
 {
 	const struct rte_cryptodev_symmetric_capability *cap;
@@ -639,6 +679,133 @@ fips_generic_test(void)
 }
 
 static int
+fips_mct_tdes_test(void)
+{
+#define TDES_BLOCK_SIZE		16
+#define TDES_EXTERN_ITER	400
+#define TDES_INTERN_ITER	10000
+	struct fips_val val, val_key;
+	uint8_t prev_out[TDES_BLOCK_SIZE];
+	uint8_t prev_prev_out[TDES_BLOCK_SIZE];
+	uint8_t prev_in[TDES_BLOCK_SIZE];
+	uint32_t i, j, k;
+	int ret;
+
+	for (i = 0; i < TDES_EXTERN_ITER; i++) {
+		if (i != 0)
+			update_info_vec(i);
+
+		fips_test_write_one_case();
+
+		for (j = 0; j < TDES_INTERN_ITER; j++) {
+			ret = fips_run_test();
+			if (ret < 0) {
+				if (ret == -EPERM) {
+					fprintf(info.fp_wr, "Bypass\n");
+					return 0;
+				}
+
+				return ret;
+			}
+
+			get_writeback_data(&val);
+
+			if (info.op == FIPS_TEST_DEC_AUTH_VERIF)
+				memcpy(prev_in, vec.ct.val, TDES_BLOCK_SIZE);
+
+			if (j == 0) {
+				memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
+
+				if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+					memcpy(vec.pt.val, vec.iv.val,
+							TDES_BLOCK_SIZE);
+					memcpy(vec.iv.val, val.val,
+							TDES_BLOCK_SIZE);
+				} else {
+					memcpy(vec.iv.val, vec.ct.val,
+							TDES_BLOCK_SIZE);
+					memcpy(vec.ct.val, val.val,
+							TDES_BLOCK_SIZE);
+				}
+				continue;
+			}
+
+			if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+				memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
+				memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
+			} else {
+				memcpy(vec.iv.val, vec.ct.val, TDES_BLOCK_SIZE);
+				memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
+			}
+
+			if (j == TDES_INTERN_ITER - 1)
+				continue;
+
+			memcpy(prev_out, val.val, TDES_BLOCK_SIZE);
+
+			if (j == TDES_INTERN_ITER - 3)
+				memcpy(prev_prev_out, val.val, TDES_BLOCK_SIZE);
+		}
+
+		info.parse_writeback(&val);
+		fprintf(info.fp_wr, "\n");
+
+		if (i == TDES_EXTERN_ITER - 1)
+			continue;
+
+		/** update key */
+		memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key));
+
+		if (info.interim_info.tdes_data.nb_keys == 0) {
+			if (memcmp(val_key.val, val_key.val + 8, 8) == 0)
+				info.interim_info.tdes_data.nb_keys = 1;
+			else if (memcmp(val_key.val, val_key.val + 16, 8) == 0)
+				info.interim_info.tdes_data.nb_keys = 2;
+			else
+				info.interim_info.tdes_data.nb_keys = 3;
+
+		}
+
+		for (k = 0; k < TDES_BLOCK_SIZE; k++) {
+
+			switch (info.interim_info.tdes_data.nb_keys) {
+			case 3:
+				val_key.val[k] ^= val.val[k];
+				val_key.val[k + 8] ^= prev_out[k];
+				val_key.val[k + 16] ^= prev_prev_out[k];
+				break;
+			case 2:
+				val_key.val[k] ^= val.val[k];
+				val_key.val[k + 8] ^= prev_out[k];
+				val_key.val[k + 16] ^= val.val[k];
+				break;
+			default: /* case 1 */
+				val_key.val[k] ^= val.val[k];
+				val_key.val[k + 8] ^= val.val[k];
+				val_key.val[k + 16] ^= val.val[k];
+				break;
+			}
+
+		}
+
+		for (k = 0; k < 24; k++)
+			val_key.val[k] = (__builtin_popcount(val_key.val[k]) &
+					0x1) ?
+					val_key.val[k] : (val_key.val[k] ^ 0x1);
+
+		if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
+			memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE);
+			memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE);
+		} else {
+			memcpy(vec.iv.val, prev_out, TDES_BLOCK_SIZE);
+			memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE);
+		}
+	}
+
+	return 0;
+}
+
+static int
 fips_mct_aes_test(void)
 {
 #define AES_BLOCK_SIZE	16
@@ -757,6 +924,14 @@ init_test_ops(void)
 		test_ops.prepare_xform = prepare_hmac_xform;
 		test_ops.test = fips_generic_test;
 		break;
+	case FIPS_TEST_ALGO_TDES:
+		test_ops.prepare_op = prepare_cipher_op;
+		test_ops.prepare_xform  = prepare_tdes_xform;
+		if (info.interim_info.tdes_data.test_type == TDES_MCT)
+			test_ops.test = fips_mct_tdes_test;
+		else
+			test_ops.test = fips_generic_test;
+		break;
 
 	default:
 		return -1;
diff --git a/examples/cryptodev_fips_validate/meson.build b/examples/cryptodev_fips_validate/meson.build
index dcf90bbbb..a18e76d4b 100644
--- a/examples/cryptodev_fips_validate/meson.build
+++ b/examples/cryptodev_fips_validate/meson.build
@@ -11,6 +11,7 @@ allow_experimental_apis = true
 sources = files(
 	'cryptodev_fips_parse_aes.c',
 	'cryptodev_fips_parse_hmac.c',
+	'cryptodev_fips_parse_3des.c',
 	'cryptodev_fips_parse_validate.c',
 	'main.c'
 )
-- 
2.13.6



More information about the dev mailing list