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