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