xref: /dpdk/examples/fips_validation/fips_validation_gcm.c (revision daa02b5cddbb8e11b31d41e2bf7bb1ae64dcae2f)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Intel Corporation
3  */
4 
5 #include <string.h>
6 #include <time.h>
7 #include <stdio.h>
8 
9 #include <rte_cryptodev.h>
10 #include <rte_malloc.h>
11 
12 #include "fips_validation.h"
13 
14 #define NEW_LINE_STR	"#"
15 #define OP_STR		"GCM "
16 
17 #define PARAM_PREFIX	"["
18 #define KEYLEN_STR	"Keylen = "
19 #define IVLEN_STR	"IVlen = "
20 #define PTLEN_STR	"PTlen = "
21 #define AADLEN_STR	"AADlen = "
22 #define TAGLEN_STR	"Taglen = "
23 
24 #define COUNT_STR	"Count = "
25 #define KEY_STR		"Key = "
26 #define IV_STR		"IV = "
27 #define PT_STR		"PT = "
28 #define CT_STR		"CT = "
29 #define TAG_STR		"Tag = "
30 #define AAD_STR		"AAD = "
31 
32 #define OP_ENC_STR	"Encrypt"
33 #define OP_DEC_STR	"Decrypt"
34 /* External/Internal IV generation, specified in file name, following NIST
35  * GCMVS Section 6.1
36  */
37 #define OP_ENC_EXT_STR	"ExtIV"
38 #define OP_ENC_INT_STR	"IntIV"
39 
40 #define NEG_TEST_STR	"FAIL"
41 
42 /**
43  * GMAC is essentially zero length plaintext and uses AAD as input data.
44  * NIST does not have GMAC specific test vector but using zero length "PTlen"
45  * and uses AAD as input.
46  **/
47 static int
48 parser_read_gcm_pt_len(const char *key, char *src,
49 		__rte_unused struct fips_val *val)
50 {
51 	int ret = parser_read_uint32_bit_val(key, src, &vec.pt);
52 
53 	if (ret < 0)
54 		return ret;
55 
56 	if (vec.pt.len == 0) {
57 		info.interim_info.gcm_data.is_gmac = 1;
58 		test_ops.prepare_op = prepare_auth_op;
59 		test_ops.prepare_xform = prepare_gmac_xform;
60 	} else {
61 		info.interim_info.gcm_data.is_gmac = 0;
62 		test_ops.prepare_op = prepare_aead_op;
63 		test_ops.prepare_xform = prepare_gcm_xform;
64 	}
65 
66 	return ret;
67 }
68 
69 static int
70 parse_gcm_aad_str(const char *key, char *src,
71 		__rte_unused struct fips_val *val)
72 {
73 	/* For GMAC test vector, AAD is treated as input */
74 	if (info.interim_info.gcm_data.is_gmac) {
75 		vec.pt.len = vec.aead.aad.len;
76 		return parse_uint8_known_len_hex_str(key, src, &vec.pt);
77 	} else /* gcm */
78 		return parse_uint8_known_len_hex_str(key, src, &vec.aead.aad);
79 }
80 
81 static int
82 parse_gcm_pt_ct_str(const char *key, char *src, struct fips_val *val)
83 {
84 	/* According to NIST GCMVS section 6.1, IUT should generate IV data */
85 	if (info.interim_info.gcm_data.gen_iv && vec.iv.len) {
86 		uint32_t i;
87 
88 		if (!vec.iv.val) {
89 			vec.iv.val = rte_malloc(0, vec.iv.len, 0);
90 			if (!vec.iv.val)
91 				return -ENOMEM;
92 		}
93 
94 		for (i = 0; i < vec.iv.len; i++) {
95 			int random = rand();
96 			vec.iv.val[i] = (uint8_t)random;
97 		}
98 	}
99 
100 	/* if PTlen == 0, pt or ct will be handled by AAD later */
101 	if (info.interim_info.gcm_data.is_gmac)
102 		return 0;
103 
104 	return parse_uint8_known_len_hex_str(key, src, val);
105 }
106 
107 struct fips_test_callback gcm_dec_vectors[] = {
108 		{KEY_STR, parse_uint8_known_len_hex_str, &vec.aead.key},
109 		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
110 		{CT_STR, parse_gcm_pt_ct_str, &vec.ct},
111 		{AAD_STR, parse_gcm_aad_str, &vec.aead.aad},
112 		{TAG_STR, parse_uint8_known_len_hex_str,
113 				&vec.aead.digest},
114 		{NULL, NULL, NULL} /**< end pointer */
115 };
116 
117 struct fips_test_callback gcm_interim_vectors[] = {
118 		{KEYLEN_STR, parser_read_uint32_bit_val, &vec.aead.key},
119 		{IVLEN_STR, parser_read_uint32_bit_val, &vec.iv},
120 		{PTLEN_STR, parser_read_gcm_pt_len, &vec.pt},
121 		{PTLEN_STR, parser_read_uint32_bit_val, &vec.ct},
122 		/**< The NIST test vectors use 'PTlen' to denote input text
123 		 *  length in case of decrypt & encrypt operations.
124 		 */
125 		{AADLEN_STR, parser_read_uint32_bit_val, &vec.aead.aad},
126 		{TAGLEN_STR, parser_read_uint32_bit_val,
127 				&vec.aead.digest},
128 		{NULL, NULL, NULL} /**< end pointer */
129 };
130 
131 struct fips_test_callback gcm_enc_vectors[] = {
132 		{KEY_STR, parse_uint8_known_len_hex_str, &vec.aead.key},
133 		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
134 		{PT_STR, parse_gcm_pt_ct_str, &vec.pt},
135 		{AAD_STR, parse_gcm_aad_str, &vec.aead.aad},
136 		{NULL, NULL, NULL} /**< end pointer */
137 };
138 
139 static int
140 parse_test_gcm_writeback(struct fips_val *val)
141 {
142 	struct fips_val tmp_val;
143 
144 	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
145 		/* According to NIST GCMVS section 6.1, IUT should provide
146 		 * generate IV data
147 		 */
148 		if (info.interim_info.gcm_data.gen_iv) {
149 			fprintf(info.fp_wr, "%s", IV_STR);
150 			tmp_val.val = vec.iv.val;
151 			tmp_val.len = vec.iv.len;
152 
153 			parse_write_hex_str(&tmp_val);
154 			rte_free(vec.iv.val);
155 			vec.iv.val = NULL;
156 		}
157 
158 		fprintf(info.fp_wr, "%s", CT_STR);
159 
160 		if (!info.interim_info.gcm_data.is_gmac) {
161 			tmp_val.val = val->val;
162 			tmp_val.len = vec.pt.len;
163 
164 			parse_write_hex_str(&tmp_val);
165 		} else
166 			fprintf(info.fp_wr, "\n");
167 
168 		fprintf(info.fp_wr, "%s", TAG_STR);
169 
170 		tmp_val.val = val->val + vec.pt.len;
171 		tmp_val.len = val->len - vec.pt.len;
172 
173 		parse_write_hex_str(&tmp_val);
174 	} else {
175 		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS) {
176 			fprintf(info.fp_wr, "%s", PT_STR);
177 			if (!info.interim_info.gcm_data.is_gmac) {
178 				tmp_val.val = val->val;
179 				tmp_val.len = vec.pt.len;
180 
181 				parse_write_hex_str(&tmp_val);
182 			} else
183 				fprintf(info.fp_wr, "\n");
184 		} else
185 			fprintf(info.fp_wr, "%s\n", NEG_TEST_STR);
186 	}
187 
188 	return 0;
189 }
190 
191 int
192 parse_test_gcm_init(void)
193 {
194 	char *tmp;
195 	uint32_t i;
196 
197 
198 	for (i = 0; i < info.nb_vec_lines; i++) {
199 		char *line = info.vec[i];
200 
201 		tmp = strstr(line, OP_STR);
202 		if (tmp) {
203 			if (strstr(line, OP_ENC_STR)) {
204 				info.op = FIPS_TEST_ENC_AUTH_GEN;
205 				info.callbacks = gcm_enc_vectors;
206 				if (strstr(info.file_name, OP_ENC_INT_STR))
207 					info.interim_info.gcm_data.gen_iv = 1;
208 			} else if (strstr(line, OP_DEC_STR)) {
209 				info.op = FIPS_TEST_DEC_AUTH_VERIF;
210 				info.callbacks = gcm_dec_vectors;
211 			} else
212 				return -EINVAL;
213 		}
214 	}
215 
216 	info.interim_callbacks = gcm_interim_vectors;
217 	info.parse_writeback = parse_test_gcm_writeback;
218 
219 	return 0;
220 }
221