xref: /dpdk/examples/fips_validation/fips_validation_gcm.c (revision 96db98db69f759cdb54c02ef72c4cae760b01ab3)
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 #ifdef RTE_HAS_JANSSON
10 #include <jansson.h>
11 #endif /* RTE_HAS_JANSSON */
12 
13 #include <rte_cryptodev.h>
14 #include <rte_malloc.h>
15 
16 #include "fips_validation.h"
17 
18 #define NEW_LINE_STR	"#"
19 #define OP_STR		"GCM "
20 
21 #define PARAM_PREFIX	"["
22 #define KEYLEN_STR	"Keylen = "
23 #define IVLEN_STR	"IVlen = "
24 #define PTLEN_STR	"PTlen = "
25 #define AADLEN_STR	"AADlen = "
26 #define TAGLEN_STR	"Taglen = "
27 
28 #define COUNT_STR	"Count = "
29 #define KEY_STR		"Key = "
30 #define IV_STR		"IV = "
31 #define PT_STR		"PT = "
32 #define CT_STR		"CT = "
33 #define TAG_STR		"Tag = "
34 #define AAD_STR		"AAD = "
35 
36 #define OP_ENC_STR	"Encrypt"
37 #define OP_DEC_STR	"Decrypt"
38 /* External/Internal IV generation, specified in file name, following NIST
39  * GCMVS Section 6.1
40  */
41 #define OP_ENC_EXT_STR	"ExtIV"
42 #define OP_ENC_INT_STR	"IntIV"
43 
44 #define KEYLEN_JSON_STR		"keyLen"
45 #define IVLEN_JSON_STR		"ivLen"
46 #define PAYLOADLEN_JSON_STR	"payloadLen"
47 #define AADLEN_JSON_STR		"aadLen"
48 #define TAGLEN_JSON_STR		"tagLen"
49 
50 #define KEY_JSON_STR	"key"
51 #define IV_JSON_STR		"iv"
52 #define PT_JSON_STR		"pt"
53 #define CT_JSON_STR		"ct"
54 #define AAD_JSON_STR	"aad"
55 #define TAG_JSON_STR	"tag"
56 #define DIR_JSON_STR	"direction"
57 
58 #define OP_ENC_JSON_STR	"encrypt"
59 #define OP_DEC_JSON_STR	"decrypt"
60 
61 #define IVGEN_JSON_STR	"ivGen"
62 #define OP_ENC_EXT_JSON_STR	"external"
63 #define OP_ENC_INT_JSON_STR	"internal"
64 
65 #define NEG_TEST_STR	"FAIL"
66 
67 /**
68  * GMAC is essentially zero length plaintext and uses AAD as input data.
69  * NIST does not have GMAC specific test vector but using zero length "PTlen"
70  * and uses AAD as input.
71  **/
72 static int
73 parser_read_gcm_pt_len(const char *key, char *src,
74 		__rte_unused struct fips_val *val)
75 {
76 	int ret = parser_read_uint32_bit_val(key, src, &vec.pt);
77 
78 	if (ret < 0)
79 		return ret;
80 
81 	if (vec.pt.len == 0) {
82 		info.interim_info.gcm_data.is_gmac = 1;
83 		test_ops.prepare_op = prepare_auth_op;
84 		test_ops.prepare_xform = prepare_gmac_xform;
85 	} else {
86 		info.interim_info.gcm_data.is_gmac = 0;
87 		test_ops.prepare_op = prepare_aead_op;
88 		test_ops.prepare_xform = prepare_gcm_xform;
89 	}
90 
91 	return ret;
92 }
93 
94 static int
95 parse_gcm_aad_str(const char *key, char *src,
96 		__rte_unused struct fips_val *val)
97 {
98 	/* For GMAC test vector, AAD is treated as input */
99 	if (info.interim_info.gcm_data.is_gmac) {
100 		vec.pt.len = vec.aead.aad.len;
101 		return parse_uint8_known_len_hex_str(key, src, &vec.pt);
102 	} else /* gcm */
103 		return parse_uint8_known_len_hex_str(key, src, &vec.aead.aad);
104 }
105 
106 static int
107 parse_gcm_pt_ct_str(const char *key, char *src, struct fips_val *val)
108 {
109 	/* According to NIST GCMVS section 6.1, IUT should generate IV data */
110 	if (info.interim_info.gcm_data.gen_iv && vec.iv.len) {
111 		uint32_t i;
112 
113 		if (!vec.iv.val) {
114 			vec.iv.val = rte_malloc(0, vec.iv.len, 0);
115 			if (!vec.iv.val)
116 				return -ENOMEM;
117 		}
118 
119 		for (i = 0; i < vec.iv.len; i++) {
120 			int random = rand();
121 			vec.iv.val[i] = (uint8_t)random;
122 		}
123 	}
124 
125 	/* if PTlen == 0, pt or ct will be handled by AAD later */
126 	if (info.interim_info.gcm_data.is_gmac)
127 		return 0;
128 
129 	return parse_uint8_known_len_hex_str(key, src, val);
130 }
131 
132 struct fips_test_callback gcm_dec_vectors[] = {
133 		{KEY_STR, parse_uint8_known_len_hex_str, &vec.aead.key},
134 		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
135 		{CT_STR, parse_gcm_pt_ct_str, &vec.ct},
136 		{AAD_STR, parse_gcm_aad_str, &vec.aead.aad},
137 		{TAG_STR, parse_uint8_known_len_hex_str,
138 				&vec.aead.digest},
139 		{NULL, NULL, NULL} /**< end pointer */
140 };
141 
142 struct fips_test_callback gcm_interim_vectors[] = {
143 		{KEYLEN_STR, parser_read_uint32_bit_val, &vec.aead.key},
144 		{IVLEN_STR, parser_read_uint32_bit_val, &vec.iv},
145 		{PTLEN_STR, parser_read_gcm_pt_len, &vec.pt},
146 		{PTLEN_STR, parser_read_uint32_bit_val, &vec.ct},
147 		/**< The NIST test vectors use 'PTlen' to denote input text
148 		 *  length in case of decrypt & encrypt operations.
149 		 */
150 		{AADLEN_STR, parser_read_uint32_bit_val, &vec.aead.aad},
151 		{TAGLEN_STR, parser_read_uint32_bit_val,
152 				&vec.aead.digest},
153 		{NULL, NULL, NULL} /**< end pointer */
154 };
155 
156 struct fips_test_callback gcm_enc_vectors[] = {
157 		{KEY_STR, parse_uint8_known_len_hex_str, &vec.aead.key},
158 		{IV_STR, parse_uint8_known_len_hex_str, &vec.iv},
159 		{PT_STR, parse_gcm_pt_ct_str, &vec.pt},
160 		{AAD_STR, parse_gcm_aad_str, &vec.aead.aad},
161 		{NULL, NULL, NULL} /**< end pointer */
162 };
163 
164 #ifdef RTE_HAS_JANSSON
165 struct fips_test_callback gcm_dec_json_vectors[] = {
166 		{KEY_JSON_STR, parse_uint8_known_len_hex_str, &vec.aead.key},
167 		{IV_JSON_STR, parse_uint8_known_len_hex_str, &vec.iv},
168 		{CT_JSON_STR, parse_gcm_pt_ct_str, &vec.ct},
169 		{AAD_JSON_STR, parse_gcm_aad_str, &vec.aead.aad},
170 		{TAG_JSON_STR, parse_uint8_known_len_hex_str,
171 				&vec.aead.digest},
172 		{NULL, NULL, NULL} /**< end pointer */
173 };
174 
175 struct fips_test_callback gcm_interim_json_vectors[] = {
176 		{KEYLEN_JSON_STR, parser_read_uint32_bit_val, &vec.aead.key},
177 		{IVLEN_JSON_STR, parser_read_uint32_bit_val, &vec.iv},
178 		{PAYLOADLEN_JSON_STR, parser_read_gcm_pt_len, &vec.pt},
179 		{PAYLOADLEN_JSON_STR, parser_read_uint32_bit_val, &vec.ct},
180 		/**< The NIST json test vectors use 'payloadLen' to denote input text
181 		 *  length in case of decrypt & encrypt operations.
182 		 */
183 		{AADLEN_JSON_STR, parser_read_uint32_bit_val, &vec.aead.aad},
184 		{TAGLEN_JSON_STR, parser_read_uint32_bit_val,
185 				&vec.aead.digest},
186 		{NULL, NULL, NULL} /**< end pointer */
187 };
188 
189 struct fips_test_callback gcm_enc_json_vectors[] = {
190 		{KEY_JSON_STR, parse_uint8_known_len_hex_str, &vec.aead.key},
191 		{IV_JSON_STR, parse_uint8_known_len_hex_str, &vec.iv},
192 		{PT_JSON_STR, parse_gcm_pt_ct_str, &vec.pt},
193 		{AAD_JSON_STR, parse_gcm_aad_str, &vec.aead.aad},
194 		{NULL, NULL, NULL} /**< end pointer */
195 };
196 #endif /* RTE_HAS_JANSSON */
197 
198 static int
199 parse_test_gcm_writeback(struct fips_val *val)
200 {
201 	struct fips_val tmp_val;
202 
203 	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
204 		/* According to NIST GCMVS section 6.1, IUT should provide
205 		 * generate IV data
206 		 */
207 		if (info.interim_info.gcm_data.gen_iv) {
208 			fprintf(info.fp_wr, "%s", IV_STR);
209 			tmp_val.val = vec.iv.val;
210 			tmp_val.len = vec.iv.len;
211 
212 			parse_write_hex_str(&tmp_val);
213 			rte_free(vec.iv.val);
214 			vec.iv.val = NULL;
215 		}
216 
217 		fprintf(info.fp_wr, "%s", CT_STR);
218 
219 		if (!info.interim_info.gcm_data.is_gmac) {
220 			tmp_val.val = val->val;
221 			tmp_val.len = vec.pt.len;
222 
223 			parse_write_hex_str(&tmp_val);
224 		} else
225 			fprintf(info.fp_wr, "\n");
226 
227 		fprintf(info.fp_wr, "%s", TAG_STR);
228 
229 		tmp_val.val = val->val + vec.pt.len;
230 		tmp_val.len = val->len - vec.pt.len;
231 
232 		parse_write_hex_str(&tmp_val);
233 	} else {
234 		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS) {
235 			fprintf(info.fp_wr, "%s", PT_STR);
236 			if (!info.interim_info.gcm_data.is_gmac) {
237 				tmp_val.val = val->val;
238 				tmp_val.len = vec.pt.len;
239 
240 				parse_write_hex_str(&tmp_val);
241 			} else
242 				fprintf(info.fp_wr, "\n");
243 		} else
244 			fprintf(info.fp_wr, "%s\n", NEG_TEST_STR);
245 	}
246 
247 	return 0;
248 }
249 
250 int
251 parse_test_gcm_init(void)
252 {
253 	char *tmp;
254 	uint32_t i;
255 
256 	for (i = 0; i < info.nb_vec_lines; i++) {
257 		char *line = info.vec[i];
258 
259 		tmp = strstr(line, OP_STR);
260 		if (tmp) {
261 			if (strstr(line, OP_ENC_STR)) {
262 				info.op = FIPS_TEST_ENC_AUTH_GEN;
263 				info.callbacks = gcm_enc_vectors;
264 				if (strstr(info.file_name, OP_ENC_INT_STR))
265 					info.interim_info.gcm_data.gen_iv = 1;
266 			} else if (strstr(line, OP_DEC_STR)) {
267 				info.op = FIPS_TEST_DEC_AUTH_VERIF;
268 				info.callbacks = gcm_dec_vectors;
269 			} else
270 				return -EINVAL;
271 		}
272 	}
273 
274 	info.interim_callbacks = gcm_interim_vectors;
275 	info.parse_writeback = parse_test_gcm_writeback;
276 
277 	return 0;
278 }
279 
280 #ifdef RTE_HAS_JANSSON
281 static int
282 parse_test_gcm_json_writeback(struct fips_val *val)
283 {
284 	struct fips_val tmp_val;
285 	json_t *tcId, *tag;
286 
287 	tcId = json_object_get(json_info.json_test_case, "tcId");
288 
289 	json_info.json_write_case = json_object();
290 	json_object_set(json_info.json_write_case, "tcId", tcId);
291 
292 	if (info.op == FIPS_TEST_ENC_AUTH_GEN) {
293 		json_t *ct;
294 
295 		tmp_val.val = val->val;
296 		tmp_val.len = vec.pt.len;
297 
298 		writeback_hex_str("", info.one_line_text, &tmp_val);
299 		ct = json_string(info.one_line_text);
300 		json_object_set_new(json_info.json_write_case, CT_JSON_STR, ct);
301 
302 		if (info.interim_info.gcm_data.gen_iv) {
303 			json_t *iv;
304 			tmp_val.val = vec.iv.val;
305 			tmp_val.len = vec.iv.len;
306 
307 			writeback_hex_str("", info.one_line_text, &tmp_val);
308 			iv = json_string(info.one_line_text);
309 			json_object_set_new(json_info.json_write_case, IV_JSON_STR, iv);
310 
311 			rte_free(vec.iv.val);
312 			vec.iv.val = NULL;
313 		}
314 
315 		tmp_val.val = val->val + vec.pt.len;
316 		tmp_val.len = val->len - vec.pt.len;
317 
318 		writeback_hex_str("", info.one_line_text, &tmp_val);
319 		tag = json_string(info.one_line_text);
320 		json_object_set_new(json_info.json_write_case, TAG_JSON_STR, tag);
321 	} else {
322 		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS) {
323 			if (!info.interim_info.gcm_data.is_gmac) {
324 				tmp_val.val = val->val;
325 				tmp_val.len = vec.pt.len;
326 
327 				writeback_hex_str("", info.one_line_text, &tmp_val);
328 				json_object_set_new(json_info.json_write_case, PT_JSON_STR,
329 					json_string(info.one_line_text));
330 			}
331 		} else {
332 			json_object_set_new(json_info.json_write_case, "testPassed", json_false());
333 		}
334 	}
335 
336 	return 0;
337 }
338 
339 int
340 parse_test_gcm_json_init(void)
341 {
342 	json_t *direction_obj;
343 	const char *direction_str;
344 
345 	direction_obj = json_object_get(json_info.json_test_group, DIR_JSON_STR);
346 	direction_str = json_string_value(direction_obj);
347 	info.interim_info.gcm_data.gen_iv = 0;
348 
349 	if (strcmp(direction_str, OP_ENC_JSON_STR) == 0) {
350 		json_t *ivGen_obj = json_object_get(json_info.json_test_group, IVGEN_JSON_STR);
351 		const char *ivGen_str = json_string_value(ivGen_obj);
352 
353 		info.op = FIPS_TEST_ENC_AUTH_GEN;
354 		info.callbacks = gcm_enc_json_vectors;
355 
356 		if (strcmp(ivGen_str, OP_ENC_INT_JSON_STR) == 0)
357 			info.interim_info.gcm_data.gen_iv = 1;
358 	} else if (strcmp(direction_str, OP_DEC_JSON_STR) == 0) {
359 		info.op = FIPS_TEST_DEC_AUTH_VERIF;
360 		info.callbacks = gcm_dec_json_vectors;
361 	} else {
362 		return -EINVAL;
363 	}
364 	info.interim_callbacks = gcm_interim_json_vectors;
365 	info.parse_writeback = parse_test_gcm_json_writeback;
366 
367 	return 0;
368 }
369 
370 #endif /* RTE_HAS_JANSSON */
371