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 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 (vec.pt.len == 0) { 83 info.interim_info.gcm_data.is_gmac = 1; 84 test_ops.prepare_op = prepare_auth_op; 85 test_ops.prepare_xform = prepare_gmac_xform; 86 } else { 87 info.interim_info.gcm_data.is_gmac = 0; 88 test_ops.prepare_op = prepare_aead_op; 89 test_ops.prepare_xform = prepare_gcm_xform; 90 } 91 92 return ret; 93 } 94 95 static int 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 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 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 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 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 296 tmp_val.val = val->val; 297 tmp_val.len = vec.pt.len; 298 299 writeback_hex_str("", info.one_line_text, &tmp_val); 300 ct = json_string(info.one_line_text); 301 json_object_set_new(json_info.json_write_case, CT_JSON_STR, ct); 302 303 if (info.interim_info.gcm_data.gen_iv) { 304 json_t *iv; 305 tmp_val.val = vec.iv.val; 306 tmp_val.len = vec.iv.len; 307 308 writeback_hex_str("", info.one_line_text, &tmp_val); 309 iv = json_string(info.one_line_text); 310 json_object_set_new(json_info.json_write_case, IV_JSON_STR, iv); 311 312 rte_free(vec.iv.val); 313 vec.iv.val = NULL; 314 } 315 316 tmp_val.val = val->val + vec.pt.len; 317 tmp_val.len = val->len - vec.pt.len; 318 319 writeback_hex_str("", info.one_line_text, &tmp_val); 320 tag = json_string(info.one_line_text); 321 json_object_set_new(json_info.json_write_case, TAG_JSON_STR, tag); 322 } else { 323 if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS) { 324 if (!info.interim_info.gcm_data.is_gmac) { 325 tmp_val.val = val->val; 326 tmp_val.len = vec.pt.len; 327 328 writeback_hex_str("", info.one_line_text, &tmp_val); 329 json_object_set_new(json_info.json_write_case, PT_JSON_STR, 330 json_string(info.one_line_text)); 331 } else { 332 json_object_set_new(json_info.json_write_case, PT_JSON_STR, 333 json_string("")); 334 } 335 } else { 336 json_object_set_new(json_info.json_write_case, "testPassed", json_false()); 337 } 338 } 339 340 return 0; 341 } 342 343 int 344 parse_test_gcm_json_init(void) 345 { 346 json_t *direction_obj; 347 const char *direction_str; 348 349 direction_obj = json_object_get(json_info.json_test_group, DIR_JSON_STR); 350 direction_str = json_string_value(direction_obj); 351 info.interim_info.gcm_data.gen_iv = 0; 352 353 if (strcmp(direction_str, OP_ENC_JSON_STR) == 0) { 354 json_t *ivGen_obj = json_object_get(json_info.json_test_group, IVGEN_JSON_STR); 355 const char *ivGen_str = json_string_value(ivGen_obj); 356 357 info.op = FIPS_TEST_ENC_AUTH_GEN; 358 info.callbacks = gcm_enc_json_vectors; 359 360 if (strcmp(ivGen_str, OP_ENC_INT_JSON_STR) == 0) 361 info.interim_info.gcm_data.gen_iv = 1; 362 } else if (strcmp(direction_str, OP_DEC_JSON_STR) == 0) { 363 info.op = FIPS_TEST_DEC_AUTH_VERIF; 364 info.callbacks = gcm_dec_json_vectors; 365 } else { 366 return -EINVAL; 367 } 368 info.interim_callbacks = gcm_interim_json_vectors; 369 info.parse_writeback = parse_test_gcm_json_writeback; 370 371 return 0; 372 } 373 374 #endif /* USE_JANSSON */ 375