1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(C) 2022 Marvell. 3 */ 4 5 #include <string.h> 6 #include <time.h> 7 #include <stdio.h> 8 #include <sys/types.h> 9 #include <unistd.h> 10 11 #ifdef USE_OPENSSL 12 #include <openssl/bn.h> 13 #include <openssl/rand.h> 14 #endif /* USE_OPENSSL */ 15 16 #include <rte_cryptodev.h> 17 #include <rte_malloc.h> 18 19 #include "fips_validation.h" 20 21 #define CONFORMANCE_JSON_STR "conformance" 22 #define TESTTYPE_JSON_STR "testType" 23 #define CURVE_JSON_STR "curve" 24 #define HASH_JSON_STR "hashAlg" 25 #define RV_JSON_STR "randomValue" 26 27 #define MSG_JSON_STR "message" 28 #define QX_JSON_STR "qx" 29 #define QY_JSON_STR "qy" 30 #define R_JSON_STR "r" 31 #define S_JSON_STR "s" 32 33 #define RV_BUF_LEN (1024/8) 34 #define RV_BIT_LEN (256) 35 36 #ifdef USE_JANSSON 37 struct { 38 uint8_t type; 39 const char *desc; 40 } ecdsa_test_types[] = { 41 {ECDSA_AFT, "AFT"} 42 }; 43 44 struct { 45 enum rte_crypto_auth_algorithm auth; 46 const char *desc; 47 } ecdsa_auth_algs[] = { 48 {RTE_CRYPTO_AUTH_SHA1, "SHA-1"}, 49 {RTE_CRYPTO_AUTH_SHA224, "SHA2-224"}, 50 {RTE_CRYPTO_AUTH_SHA256, "SHA2-256"}, 51 {RTE_CRYPTO_AUTH_SHA384, "SHA2-384"}, 52 {RTE_CRYPTO_AUTH_SHA512, "SHA2-512"}, 53 {RTE_CRYPTO_AUTH_SHA3_224, "SHA3-224"}, 54 {RTE_CRYPTO_AUTH_SHA3_256, "SHA3-256"}, 55 {RTE_CRYPTO_AUTH_SHA3_384, "SHA3-384"}, 56 {RTE_CRYPTO_AUTH_SHA3_512, "SHA3-512"}, 57 }; 58 59 struct { 60 enum rte_crypto_curve_id curve_id; 61 const char *desc; 62 } ecdsa_curve_ids[] = { 63 {RTE_CRYPTO_EC_GROUP_SECP192R1, "P-192"}, 64 {RTE_CRYPTO_EC_GROUP_SECP224R1, "P-224"}, 65 {RTE_CRYPTO_EC_GROUP_SECP256R1, "P-256"}, 66 {RTE_CRYPTO_EC_GROUP_SECP384R1, "P-384"}, 67 {RTE_CRYPTO_EC_GROUP_SECP521R1, "P-521"}, 68 }; 69 70 struct { 71 uint8_t curve_len; 72 const char *desc; 73 } ecdsa_curve_len[] = { 74 {24, "P-192"}, 75 {28, "P-224"}, 76 {32, "P-256"}, 77 {48, "P-384"}, 78 {66, "P-521"}, 79 }; 80 81 #ifdef USE_OPENSSL 82 #define MAX_TRIES 10 83 static int 84 prepare_vec_ecdsa(void) 85 { 86 BIGNUM *pkey = NULL, *order = NULL, *r = NULL; 87 int ret = -1, j; 88 unsigned long pid; 89 90 /* For ECDSA prime fields, order of base points. 91 * Below string array is indexed by starting with first supported 92 * curve (SECP-192R1). 93 */ 94 static const char * const orderstr[] = { 95 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", 96 "", 97 "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", 98 "", 99 "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", 100 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", 101 "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409" 102 }; 103 104 /* Seed PRNG */ 105 if (vec.ecdsa.seed.val) { 106 writeback_hex_str("", info.one_line_text, &vec.ecdsa.seed); 107 RAND_seed((char *)info.one_line_text, strlen(info.one_line_text)); 108 } else { 109 pid = getpid(); 110 RAND_seed(&pid, sizeof(pid)); 111 } 112 113 if (!RAND_status()) 114 return -1; 115 116 order = BN_new(); 117 if (!order) 118 goto err; 119 120 j = info.interim_info.ecdsa_data.curve_id - RTE_CRYPTO_EC_GROUP_SECP192R1; 121 if (!BN_hex2bn(&order, orderstr[j])) 122 goto err; 123 124 pkey = BN_new(); 125 if (!pkey) 126 goto err; 127 128 for (j = 0; j < MAX_TRIES; j++) { 129 /* pkey should be in [1, order - 1] */ 130 if (!BN_rand_range(pkey, order)) 131 goto err; 132 133 if (!BN_is_zero(pkey)) 134 break; 135 } 136 137 if (j == MAX_TRIES) 138 goto err; 139 140 parse_uint8_hex_str("", BN_bn2hex(pkey), &vec.ecdsa.pkey); 141 142 r = BN_new(); 143 if (!r) 144 goto err; 145 146 if (info.interim_info.ecdsa_data.random_msg) { 147 if (!BN_rand(r, RV_BIT_LEN, 0, 0)) 148 goto err; 149 150 parse_uint8_hex_str("", BN_bn2hex(r), &vec.ecdsa.seed); 151 } 152 153 ret = 0; 154 err: 155 BN_free(order); 156 BN_free(pkey); 157 BN_free(r); 158 return ret; 159 } 160 161 static int 162 prepare_vec_ecdsa_k(void) 163 { 164 BIGNUM *pkey = NULL, *k = NULL; 165 int ret = -1; 166 167 if (!vec.ecdsa.pkey.len) 168 return -1; 169 170 pkey = BN_new(); 171 if (!pkey) 172 goto err; 173 174 writeback_hex_str("", info.one_line_text, &vec.ecdsa.pkey); 175 ret = BN_hex2bn(&pkey, info.one_line_text); 176 if ((uint32_t)ret != strlen(info.one_line_text)) 177 goto err; 178 179 k = BN_new(); 180 if (!k) 181 goto err; 182 183 if (!BN_sub(k, pkey, BN_value_one())) 184 goto err; 185 186 if (BN_is_zero(pkey)) { 187 if (!BN_add(k, pkey, BN_value_one())) 188 goto err; 189 } 190 191 parse_uint8_hex_str("", BN_bn2hex(k), &vec.ecdsa.k); 192 ret = 0; 193 err: 194 BN_free(pkey); 195 BN_free(k); 196 return ret; 197 } 198 199 #else 200 static int 201 prepare_vec_ecdsa(void) 202 { 203 /* 204 * Generate ECDSA values. 205 */ 206 return -ENOTSUP; 207 } 208 209 static int 210 prepare_vec_ecdsa_k(void) 211 { 212 /* 213 * Generate ECDSA values. 214 */ 215 return -ENOTSUP; 216 } 217 #endif /* USE_OPENSSL */ 218 219 static int 220 parse_test_ecdsa_json_interim_writeback(struct fips_val *val) 221 { 222 RTE_SET_USED(val); 223 224 if (info.interim_info.ecdsa_data.random_msg) { 225 json_object_set_new(json_info.json_write_group, "conformance", 226 json_string("SP800-106")); 227 } 228 229 if (info.op == FIPS_TEST_ASYM_SIGGEN) { 230 /* For siggen tests, ECDSA values can be created soon after 231 * the test group data are parsed. 232 */ 233 if (vec.ecdsa.pkey.val) { 234 rte_free(vec.ecdsa.pkey.val); 235 vec.ecdsa.pkey.val = NULL; 236 } 237 238 if (prepare_vec_ecdsa() < 0) 239 return -1; 240 241 info.interim_info.ecdsa_data.pubkey_gen = 1; 242 } 243 244 return 0; 245 } 246 247 static int 248 post_test_ecdsa_json_interim_writeback(struct fips_val *val) 249 { 250 RTE_SET_USED(val); 251 252 if (info.op == FIPS_TEST_ASYM_KEYGEN) { 253 json_t *obj; 254 255 writeback_hex_str("", info.one_line_text, &vec.ecdsa.qx); 256 obj = json_string(info.one_line_text); 257 json_object_set_new(json_info.json_write_group, "qx", obj); 258 259 writeback_hex_str("", info.one_line_text, &vec.ecdsa.qy); 260 obj = json_string(info.one_line_text); 261 json_object_set_new(json_info.json_write_group, "qy", obj); 262 } 263 264 return 0; 265 } 266 267 static int 268 parse_test_ecdsa_json_writeback(struct fips_val *val) 269 { 270 json_t *tcId; 271 272 RTE_SET_USED(val); 273 274 tcId = json_object_get(json_info.json_test_case, "tcId"); 275 276 json_info.json_write_case = json_object(); 277 json_object_set(json_info.json_write_case, "tcId", tcId); 278 279 if (info.op == FIPS_TEST_ASYM_SIGGEN) { 280 json_t *obj; 281 282 writeback_hex_str("", info.one_line_text, &vec.ecdsa.r); 283 obj = json_string(info.one_line_text); 284 json_object_set_new(json_info.json_write_case, "r", obj); 285 286 writeback_hex_str("", info.one_line_text, &vec.ecdsa.s); 287 obj = json_string(info.one_line_text); 288 json_object_set_new(json_info.json_write_case, "s", obj); 289 290 if (info.interim_info.ecdsa_data.random_msg) { 291 writeback_hex_str("", info.one_line_text, &vec.ecdsa.seed); 292 obj = json_string(info.one_line_text); 293 json_object_set_new(json_info.json_write_case, "randomValue", obj); 294 json_object_set_new(json_info.json_write_case, "randomValueLen", 295 json_integer(vec.ecdsa.seed.len * 8)); 296 } 297 } else if (info.op == FIPS_TEST_ASYM_SIGVER) { 298 if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS) 299 json_object_set_new(json_info.json_write_case, "testPassed", json_true()); 300 else 301 json_object_set_new(json_info.json_write_case, "testPassed", json_false()); 302 } else if (info.op == FIPS_TEST_ASYM_KEYGEN) { 303 json_t *obj; 304 305 writeback_hex_str("", info.one_line_text, &vec.ecdsa.pkey); 306 obj = json_string(info.one_line_text); 307 json_object_set_new(json_info.json_write_case, "d", obj); 308 309 writeback_hex_str("", info.one_line_text, &vec.ecdsa.qx); 310 obj = json_string(info.one_line_text); 311 json_object_set_new(json_info.json_write_case, "qx", obj); 312 313 writeback_hex_str("", info.one_line_text, &vec.ecdsa.qy); 314 obj = json_string(info.one_line_text); 315 json_object_set_new(json_info.json_write_case, "qy", obj); 316 } 317 318 return 0; 319 } 320 321 static int 322 parse_interim_str(const char *key, char *src, struct fips_val *val) 323 { 324 uint32_t i; 325 326 RTE_SET_USED(val); 327 328 if (strcmp(key, TESTTYPE_JSON_STR) == 0) { 329 for (i = 0; i < RTE_DIM(ecdsa_test_types); i++) 330 if (strstr(src, ecdsa_test_types[i].desc)) { 331 info.parse_writeback = parse_test_ecdsa_json_writeback; 332 break; 333 } 334 335 if (!info.parse_writeback || i >= RTE_DIM(ecdsa_test_types)) 336 return -EINVAL; 337 338 } else if (strcmp(key, CURVE_JSON_STR) == 0) { 339 for (i = 0; i < RTE_DIM(ecdsa_curve_ids); i++) 340 if (strstr(src, ecdsa_curve_ids[i].desc)) { 341 info.interim_info.ecdsa_data.curve_id = ecdsa_curve_ids[i].curve_id; 342 info.interim_info.ecdsa_data.curve_len = 343 ecdsa_curve_len[i].curve_len; 344 break; 345 } 346 347 if (i >= RTE_DIM(ecdsa_curve_ids)) 348 return -EINVAL; 349 } else if (strcmp(key, HASH_JSON_STR) == 0) { 350 for (i = 0; i < RTE_DIM(ecdsa_auth_algs); i++) 351 if (strstr(src, ecdsa_auth_algs[i].desc)) { 352 info.interim_info.ecdsa_data.auth = ecdsa_auth_algs[i].auth; 353 break; 354 } 355 356 if (i >= RTE_DIM(ecdsa_auth_algs)) 357 return -EINVAL; 358 } else if (strcmp(key, CONFORMANCE_JSON_STR) == 0) { 359 info.interim_info.ecdsa_data.random_msg = 1; 360 } else { 361 return -EINVAL; 362 } 363 364 return 0; 365 } 366 367 static int 368 parse_siggen_message_str(const char *key, char *src, struct fips_val *val) 369 { 370 int ret = 0; 371 372 parse_uint8_hex_str(key, src, val); 373 if (info.interim_info.ecdsa_data.random_msg) { 374 ret = fips_test_randomize_message(val, &vec.ecdsa.seed); 375 if (ret < 0) 376 return ret; 377 } 378 379 if (vec.ecdsa.k.val) { 380 rte_free(vec.ecdsa.k.val); 381 vec.ecdsa.k.val = NULL; 382 } 383 384 ret = prepare_vec_ecdsa_k(); 385 return ret; 386 } 387 388 static int 389 parse_keygen_tc_str(const char *key, char *src, struct fips_val *val) 390 { 391 RTE_SET_USED(key); 392 RTE_SET_USED(src); 393 RTE_SET_USED(val); 394 395 if (info.op == FIPS_TEST_ASYM_KEYGEN) { 396 if (vec.ecdsa.pkey.val) { 397 rte_free(vec.ecdsa.pkey.val); 398 vec.ecdsa.pkey.val = NULL; 399 } 400 401 if (vec.ecdsa.k.val) { 402 rte_free(vec.ecdsa.k.val); 403 vec.ecdsa.k.val = NULL; 404 } 405 406 if (prepare_vec_ecdsa() < 0) 407 return -1; 408 409 if (prepare_vec_ecdsa_k() < 0) 410 return -1; 411 412 info.interim_info.ecdsa_data.pubkey_gen = 1; 413 } 414 415 return 0; 416 } 417 418 static int 419 parse_sigver_randomvalue_str(const char *key, char *src, struct fips_val *val) 420 { 421 int ret = 0; 422 423 parse_uint8_hex_str(key, src, val); 424 if (info.interim_info.ecdsa_data.random_msg) 425 ret = fips_test_randomize_message(&vec.pt, val); 426 427 return ret; 428 } 429 430 struct fips_test_callback ecdsa_interim_json_vectors[] = { 431 {TESTTYPE_JSON_STR, parse_interim_str, NULL}, 432 {CURVE_JSON_STR, parse_interim_str, NULL}, 433 {HASH_JSON_STR, parse_interim_str, NULL}, 434 {CONFORMANCE_JSON_STR, parse_interim_str, NULL}, 435 {NULL, NULL, NULL} /**< end pointer */ 436 }; 437 438 struct fips_test_callback ecdsa_siggen_json_vectors[] = { 439 {MSG_JSON_STR, parse_siggen_message_str, &vec.pt}, 440 {NULL, NULL, NULL} /**< end pointer */ 441 }; 442 443 struct fips_test_callback ecdsa_sigver_json_vectors[] = { 444 {MSG_JSON_STR, parse_uint8_hex_str, &vec.pt}, 445 {QX_JSON_STR, parse_uint8_hex_str, &vec.ecdsa.qx}, 446 {QY_JSON_STR, parse_uint8_hex_str, &vec.ecdsa.qy}, 447 {R_JSON_STR, parse_uint8_hex_str, &vec.ecdsa.r}, 448 {S_JSON_STR, parse_uint8_hex_str, &vec.ecdsa.s}, 449 {RV_JSON_STR, parse_sigver_randomvalue_str, &vec.ecdsa.seed}, 450 {NULL, NULL, NULL} /**< end pointer */ 451 }; 452 453 struct fips_test_callback ecdsa_keygen_json_vectors[] = { 454 {"tcId", parse_keygen_tc_str, &vec.pt}, 455 {NULL, NULL, NULL} /**< end pointer */ 456 }; 457 458 int 459 parse_test_ecdsa_json_init(void) 460 { 461 json_t *mode_obj = json_object_get(json_info.json_vector_set, "mode"); 462 const char *mode_str = json_string_value(mode_obj); 463 464 info.callbacks = NULL; 465 info.parse_writeback = NULL; 466 info.interim_info.ecdsa_data.random_msg = 0; 467 468 info.interim_callbacks = ecdsa_interim_json_vectors; 469 info.post_interim_writeback = post_test_ecdsa_json_interim_writeback; 470 info.parse_interim_writeback = parse_test_ecdsa_json_interim_writeback; 471 if (strcmp(mode_str, "sigGen") == 0) { 472 info.op = FIPS_TEST_ASYM_SIGGEN; 473 info.callbacks = ecdsa_siggen_json_vectors; 474 } else if (strcmp(mode_str, "sigVer") == 0) { 475 info.op = FIPS_TEST_ASYM_SIGVER; 476 info.callbacks = ecdsa_sigver_json_vectors; 477 } else if (strcmp(mode_str, "keyGen") == 0) { 478 info.op = FIPS_TEST_ASYM_KEYGEN; 479 info.callbacks = ecdsa_keygen_json_vectors; 480 } else { 481 return -EINVAL; 482 } 483 484 return 0; 485 } 486 #endif /* USE_JANSSON */ 487