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