1/* 2 * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10/* 11 * Low level APIs are deprecated for public use, but still ok for internal use. 12 */ 13#include "internal/deprecated.h" 14 15#include "internal/nelem.h" 16#include "testutil.h" 17#include <openssl/ec.h> 18#include "ec_local.h" 19#include <openssl/objects.h> 20 21static size_t crv_len = 0; 22static EC_builtin_curve *curves = NULL; 23 24/* sanity checks field_inv function pointer in EC_METHOD */ 25static int group_field_tests(const EC_GROUP *group, BN_CTX *ctx) 26{ 27 BIGNUM *a = NULL, *b = NULL, *c = NULL; 28 int ret = 0; 29 30 if (group->meth->field_inv == NULL || group->meth->field_mul == NULL) 31 return 1; 32 33 BN_CTX_start(ctx); 34 a = BN_CTX_get(ctx); 35 b = BN_CTX_get(ctx); 36 if (!TEST_ptr(c = BN_CTX_get(ctx)) 37 /* 1/1 = 1 */ 38 || !TEST_true(group->meth->field_inv(group, b, BN_value_one(), ctx)) 39 || !TEST_true(BN_is_one(b)) 40 /* (1/a)*a = 1 */ 41 || !TEST_true(BN_rand(a, BN_num_bits(group->field) - 1, 42 BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) 43 || !TEST_true(group->meth->field_inv(group, b, a, ctx)) 44 || (group->meth->field_encode && 45 !TEST_true(group->meth->field_encode(group, a, a, ctx))) 46 || (group->meth->field_encode && 47 !TEST_true(group->meth->field_encode(group, b, b, ctx))) 48 || !TEST_true(group->meth->field_mul(group, c, a, b, ctx)) 49 || (group->meth->field_decode && 50 !TEST_true(group->meth->field_decode(group, c, c, ctx))) 51 || !TEST_true(BN_is_one(c))) 52 goto err; 53 54 /* 1/0 = error */ 55 BN_zero(a); 56 if (!TEST_false(group->meth->field_inv(group, b, a, ctx)) 57 || !TEST_true(ERR_GET_LIB(ERR_peek_last_error()) == ERR_LIB_EC) 58 || !TEST_true(ERR_GET_REASON(ERR_peek_last_error()) == 59 EC_R_CANNOT_INVERT) 60 /* 1/p = error */ 61 || !TEST_false(group->meth->field_inv(group, b, group->field, ctx)) 62 || !TEST_true(ERR_GET_LIB(ERR_peek_last_error()) == ERR_LIB_EC) 63 || !TEST_true(ERR_GET_REASON(ERR_peek_last_error()) == 64 EC_R_CANNOT_INVERT)) 65 goto err; 66 67 ERR_clear_error(); 68 ret = 1; 69 err: 70 BN_CTX_end(ctx); 71 return ret; 72} 73 74/* wrapper for group_field_tests for explicit curve params and EC_METHOD */ 75static int field_tests(const EC_METHOD *meth, const unsigned char *params, 76 int len) 77{ 78 BN_CTX *ctx = NULL; 79 BIGNUM *p = NULL, *a = NULL, *b = NULL; 80 EC_GROUP *group = NULL; 81 int ret = 0; 82 83 if (!TEST_ptr(ctx = BN_CTX_new())) 84 return 0; 85 86 BN_CTX_start(ctx); 87 p = BN_CTX_get(ctx); 88 a = BN_CTX_get(ctx); 89 if (!TEST_ptr(b = BN_CTX_get(ctx)) 90 || !TEST_ptr(group = EC_GROUP_new(meth)) 91 || !TEST_true(BN_bin2bn(params, len, p)) 92 || !TEST_true(BN_bin2bn(params + len, len, a)) 93 || !TEST_true(BN_bin2bn(params + 2 * len, len, b)) 94 || !TEST_true(EC_GROUP_set_curve(group, p, a, b, ctx)) 95 || !group_field_tests(group, ctx)) 96 goto err; 97 ret = 1; 98 99 err: 100 BN_CTX_end(ctx); 101 BN_CTX_free(ctx); 102 if (group != NULL) 103 EC_GROUP_free(group); 104 return ret; 105} 106 107/* NIST prime curve P-256 */ 108static const unsigned char params_p256[] = { 109 /* p */ 110 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 112 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 113 /* a */ 114 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 115 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 116 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 117 /* b */ 118 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55, 119 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6, 120 0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B 121}; 122 123#ifndef OPENSSL_NO_EC2M 124/* NIST binary curve B-283 */ 125static const unsigned char params_b283[] = { 126 /* p */ 127 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA1, 130 /* a */ 131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 134 /* b */ 135 0x02, 0x7B, 0x68, 0x0A, 0xC8, 0xB8, 0x59, 0x6D, 0xA5, 0xA4, 0xAF, 0x8A, 136 0x19, 0xA0, 0x30, 0x3F, 0xCA, 0x97, 0xFD, 0x76, 0x45, 0x30, 0x9F, 0xA2, 137 0xA5, 0x81, 0x48, 0x5A, 0xF6, 0x26, 0x3E, 0x31, 0x3B, 0x79, 0xA2, 0xF5 138}; 139#endif 140 141/* test EC_GFp_simple_method directly */ 142static int field_tests_ecp_simple(void) 143{ 144 TEST_info("Testing EC_GFp_simple_method()\n"); 145 return field_tests(EC_GFp_simple_method(), params_p256, 146 sizeof(params_p256) / 3); 147} 148 149/* test EC_GFp_mont_method directly */ 150static int field_tests_ecp_mont(void) 151{ 152 TEST_info("Testing EC_GFp_mont_method()\n"); 153 return field_tests(EC_GFp_mont_method(), params_p256, 154 sizeof(params_p256) / 3); 155} 156 157#ifndef OPENSSL_NO_EC2M 158/* Test that decoding of invalid GF2m field parameters fails. */ 159static int ec2m_field_sanity(void) 160{ 161 int ret = 0; 162 BN_CTX *ctx = BN_CTX_new(); 163 BIGNUM *p, *a, *b; 164 EC_GROUP *group1 = NULL, *group2 = NULL, *group3 = NULL; 165 166 TEST_info("Testing GF2m hardening\n"); 167 168 BN_CTX_start(ctx); 169 p = BN_CTX_get(ctx); 170 a = BN_CTX_get(ctx); 171 if (!TEST_ptr(b = BN_CTX_get(ctx)) 172 || !TEST_true(BN_one(a)) 173 || !TEST_true(BN_one(b))) 174 goto out; 175 176 /* Even pentanomial value should be rejected */ 177 if (!TEST_true(BN_set_word(p, 0xf2))) 178 goto out; 179 if (!TEST_ptr_null(group1 = EC_GROUP_new_curve_GF2m(p, a, b, ctx))) 180 TEST_error("Zero constant term accepted in GF2m polynomial"); 181 182 /* Odd hexanomial should also be rejected */ 183 if (!TEST_true(BN_set_word(p, 0xf3))) 184 goto out; 185 if (!TEST_ptr_null(group2 = EC_GROUP_new_curve_GF2m(p, a, b, ctx))) 186 TEST_error("Hexanomial accepted as GF2m polynomial"); 187 188 /* Excessive polynomial degree should also be rejected */ 189 if (!TEST_true(BN_set_word(p, 0x71)) 190 || !TEST_true(BN_set_bit(p, OPENSSL_ECC_MAX_FIELD_BITS + 1))) 191 goto out; 192 if (!TEST_ptr_null(group3 = EC_GROUP_new_curve_GF2m(p, a, b, ctx))) 193 TEST_error("GF2m polynomial degree > %d accepted", 194 OPENSSL_ECC_MAX_FIELD_BITS); 195 196 ret = group1 == NULL && group2 == NULL && group3 == NULL; 197 198 out: 199 EC_GROUP_free(group1); 200 EC_GROUP_free(group2); 201 EC_GROUP_free(group3); 202 BN_CTX_end(ctx); 203 BN_CTX_free(ctx); 204 205 return ret; 206} 207 208/* test EC_GF2m_simple_method directly */ 209static int field_tests_ec2_simple(void) 210{ 211 TEST_info("Testing EC_GF2m_simple_method()\n"); 212 return field_tests(EC_GF2m_simple_method(), params_b283, 213 sizeof(params_b283) / 3); 214} 215#endif 216 217/* test default method for a named curve */ 218static int field_tests_default(int n) 219{ 220 BN_CTX *ctx = NULL; 221 EC_GROUP *group = NULL; 222 int nid = curves[n].nid; 223 int ret = 0; 224 225 TEST_info("Testing curve %s\n", OBJ_nid2sn(nid)); 226 227 if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(nid)) 228 || !TEST_ptr(ctx = BN_CTX_new()) 229 || !group_field_tests(group, ctx)) 230 goto err; 231 232 ret = 1; 233 err: 234 if (group != NULL) 235 EC_GROUP_free(group); 236 if (ctx != NULL) 237 BN_CTX_free(ctx); 238 return ret; 239} 240 241#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 242/* 243 * Tests a point known to cause an incorrect underflow in an old version of 244 * ecp_nist521.c 245 */ 246static int underflow_test(void) 247{ 248 BN_CTX *ctx = NULL; 249 EC_GROUP *grp = NULL; 250 EC_POINT *P = NULL, *Q = NULL, *R = NULL; 251 BIGNUM *x1 = NULL, *y1 = NULL, *z1 = NULL, *x2 = NULL, *y2 = NULL; 252 BIGNUM *k = NULL; 253 int testresult = 0; 254 const char *x1str = 255 "1534f0077fffffe87e9adcfe000000000000000000003e05a21d2400002e031b1f4" 256 "b80000c6fafa4f3c1288798d624a247b5e2ffffffffffffffefe099241900004"; 257 const char *p521m1 = 258 "1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" 259 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"; 260 261 ctx = BN_CTX_new(); 262 if (!TEST_ptr(ctx)) 263 return 0; 264 265 BN_CTX_start(ctx); 266 x1 = BN_CTX_get(ctx); 267 y1 = BN_CTX_get(ctx); 268 z1 = BN_CTX_get(ctx); 269 x2 = BN_CTX_get(ctx); 270 y2 = BN_CTX_get(ctx); 271 k = BN_CTX_get(ctx); 272 if (!TEST_ptr(k)) 273 goto err; 274 275 grp = EC_GROUP_new_by_curve_name(NID_secp521r1); 276 P = EC_POINT_new(grp); 277 Q = EC_POINT_new(grp); 278 R = EC_POINT_new(grp); 279 if (!TEST_ptr(grp) || !TEST_ptr(P) || !TEST_ptr(Q) || !TEST_ptr(R)) 280 goto err; 281 282 if (!TEST_int_gt(BN_hex2bn(&x1, x1str), 0) 283 || !TEST_int_gt(BN_hex2bn(&y1, p521m1), 0) 284 || !TEST_int_gt(BN_hex2bn(&z1, p521m1), 0) 285 || !TEST_int_gt(BN_hex2bn(&k, "02"), 0) 286 || !TEST_true(ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(grp, P, x1, 287 y1, z1, ctx)) 288 || !TEST_true(EC_POINT_mul(grp, Q, NULL, P, k, ctx)) 289 || !TEST_true(EC_POINT_get_affine_coordinates(grp, Q, x1, y1, ctx)) 290 || !TEST_true(EC_POINT_dbl(grp, R, P, ctx)) 291 || !TEST_true(EC_POINT_get_affine_coordinates(grp, R, x2, y2, ctx))) 292 goto err; 293 294 if (!TEST_int_eq(BN_cmp(x1, x2), 0) 295 || !TEST_int_eq(BN_cmp(y1, y2), 0)) 296 goto err; 297 298 testresult = 1; 299 300 err: 301 BN_CTX_end(ctx); 302 EC_POINT_free(P); 303 EC_POINT_free(Q); 304 EC_POINT_free(R); 305 EC_GROUP_free(grp); 306 BN_CTX_free(ctx); 307 308 return testresult; 309} 310#endif 311 312/* 313 * Tests behavior of the EC_KEY_set_private_key 314 */ 315static int set_private_key(void) 316{ 317 EC_KEY *key = NULL, *aux_key = NULL; 318 int testresult = 0; 319 320 key = EC_KEY_new_by_curve_name(NID_secp224r1); 321 aux_key = EC_KEY_new_by_curve_name(NID_secp224r1); 322 if (!TEST_ptr(key) 323 || !TEST_ptr(aux_key) 324 || !TEST_int_eq(EC_KEY_generate_key(key), 1) 325 || !TEST_int_eq(EC_KEY_generate_key(aux_key), 1)) 326 goto err; 327 328 /* Test setting a valid private key */ 329 if (!TEST_int_eq(EC_KEY_set_private_key(key, aux_key->priv_key), 1)) 330 goto err; 331 332 /* Test compliance with legacy behavior for NULL private keys */ 333 if (!TEST_int_eq(EC_KEY_set_private_key(key, NULL), 0) 334 || !TEST_ptr_null(key->priv_key)) 335 goto err; 336 337 testresult = 1; 338 339 err: 340 EC_KEY_free(key); 341 EC_KEY_free(aux_key); 342 return testresult; 343} 344 345/* 346 * Tests behavior of the decoded_from_explicit_params flag and API 347 */ 348static int decoded_flag_test(void) 349{ 350 EC_GROUP *grp; 351 EC_GROUP *grp_copy = NULL; 352 ECPARAMETERS *ecparams = NULL; 353 ECPKPARAMETERS *ecpkparams = NULL; 354 EC_KEY *key = NULL; 355 unsigned char *encodedparams = NULL; 356 const unsigned char *encp; 357 int encodedlen; 358 int testresult = 0; 359 360 /* Test EC_GROUP_new not setting the flag */ 361 grp = EC_GROUP_new(EC_GFp_simple_method()); 362 if (!TEST_ptr(grp) 363 || !TEST_int_eq(grp->decoded_from_explicit_params, 0)) 364 goto err; 365 EC_GROUP_free(grp); 366 367 /* Test EC_GROUP_new_by_curve_name not setting the flag */ 368 grp = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); 369 if (!TEST_ptr(grp) 370 || !TEST_int_eq(grp->decoded_from_explicit_params, 0)) 371 goto err; 372 373 /* Test EC_GROUP_new_from_ecparameters not setting the flag */ 374 if (!TEST_ptr(ecparams = EC_GROUP_get_ecparameters(grp, NULL)) 375 || !TEST_ptr(grp_copy = EC_GROUP_new_from_ecparameters(ecparams)) 376 || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0)) 377 goto err; 378 EC_GROUP_free(grp_copy); 379 grp_copy = NULL; 380 ECPARAMETERS_free(ecparams); 381 ecparams = NULL; 382 383 /* Test EC_GROUP_new_from_ecpkparameters not setting the flag */ 384 if (!TEST_int_eq(EC_GROUP_get_asn1_flag(grp), OPENSSL_EC_NAMED_CURVE) 385 || !TEST_ptr(ecpkparams = EC_GROUP_get_ecpkparameters(grp, NULL)) 386 || !TEST_ptr(grp_copy = EC_GROUP_new_from_ecpkparameters(ecpkparams)) 387 || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0) 388 || !TEST_ptr(key = EC_KEY_new()) 389 /* Test EC_KEY_decoded_from_explicit_params on key without a group */ 390 || !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), -1) 391 || !TEST_int_eq(EC_KEY_set_group(key, grp_copy), 1) 392 /* Test EC_KEY_decoded_from_explicit_params negative case */ 393 || !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), 0)) 394 goto err; 395 EC_GROUP_free(grp_copy); 396 grp_copy = NULL; 397 ECPKPARAMETERS_free(ecpkparams); 398 ecpkparams = NULL; 399 400 /* Test d2i_ECPKParameters with named params not setting the flag */ 401 if (!TEST_int_gt(encodedlen = i2d_ECPKParameters(grp, &encodedparams), 0) 402 || !TEST_ptr(encp = encodedparams) 403 || !TEST_ptr(grp_copy = d2i_ECPKParameters(NULL, &encp, encodedlen)) 404 || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0)) 405 goto err; 406 EC_GROUP_free(grp_copy); 407 grp_copy = NULL; 408 OPENSSL_free(encodedparams); 409 encodedparams = NULL; 410 411 /* Asn1 flag stays set to explicit with EC_GROUP_new_from_ecpkparameters */ 412 EC_GROUP_set_asn1_flag(grp, OPENSSL_EC_EXPLICIT_CURVE); 413 if (!TEST_ptr(ecpkparams = EC_GROUP_get_ecpkparameters(grp, NULL)) 414 || !TEST_ptr(grp_copy = EC_GROUP_new_from_ecpkparameters(ecpkparams)) 415 || !TEST_int_eq(EC_GROUP_get_asn1_flag(grp_copy), OPENSSL_EC_EXPLICIT_CURVE) 416 || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0)) 417 goto err; 418 EC_GROUP_free(grp_copy); 419 grp_copy = NULL; 420 421 /* Test d2i_ECPKParameters with explicit params setting the flag */ 422 if (!TEST_int_gt(encodedlen = i2d_ECPKParameters(grp, &encodedparams), 0) 423 || !TEST_ptr(encp = encodedparams) 424 || !TEST_ptr(grp_copy = d2i_ECPKParameters(NULL, &encp, encodedlen)) 425 || !TEST_int_eq(EC_GROUP_get_asn1_flag(grp_copy), OPENSSL_EC_EXPLICIT_CURVE) 426 || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 1) 427 || !TEST_int_eq(EC_KEY_set_group(key, grp_copy), 1) 428 /* Test EC_KEY_decoded_from_explicit_params positive case */ 429 || !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), 1)) 430 goto err; 431 432 testresult = 1; 433 434 err: 435 EC_KEY_free(key); 436 EC_GROUP_free(grp); 437 EC_GROUP_free(grp_copy); 438 ECPARAMETERS_free(ecparams); 439 ECPKPARAMETERS_free(ecpkparams); 440 OPENSSL_free(encodedparams); 441 442 return testresult; 443} 444 445static 446int ecpkparams_i2d2i_test(int n) 447{ 448 EC_GROUP *g1 = NULL, *g2 = NULL; 449 FILE *fp = NULL; 450 int nid = curves[n].nid; 451 int testresult = 0; 452 453 /* create group */ 454 if (!TEST_ptr(g1 = EC_GROUP_new_by_curve_name(nid))) 455 goto end; 456 457 /* encode params to file */ 458 if (!TEST_ptr(fp = fopen("params.der", "wb")) 459 || !TEST_true(i2d_ECPKParameters_fp(fp, g1))) 460 goto end; 461 462 /* flush and close file */ 463 if (!TEST_int_eq(fclose(fp), 0)) { 464 fp = NULL; 465 goto end; 466 } 467 fp = NULL; 468 469 /* decode params from file */ 470 if (!TEST_ptr(fp = fopen("params.der", "rb")) 471 || !TEST_ptr(g2 = d2i_ECPKParameters_fp(fp, NULL))) 472 goto end; 473 474 testresult = 1; /* PASS */ 475 476end: 477 if (fp != NULL) 478 fclose(fp); 479 480 EC_GROUP_free(g1); 481 EC_GROUP_free(g2); 482 483 return testresult; 484} 485 486int setup_tests(void) 487{ 488 crv_len = EC_get_builtin_curves(NULL, 0); 489 if (!TEST_ptr(curves = OPENSSL_malloc(sizeof(*curves) * crv_len)) 490 || !TEST_true(EC_get_builtin_curves(curves, crv_len))) 491 return 0; 492 493 ADD_TEST(field_tests_ecp_simple); 494 ADD_TEST(field_tests_ecp_mont); 495#ifndef OPENSSL_NO_EC2M 496 ADD_TEST(ec2m_field_sanity); 497 ADD_TEST(field_tests_ec2_simple); 498#endif 499 ADD_ALL_TESTS(field_tests_default, crv_len); 500#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 501 ADD_TEST(underflow_test); 502#endif 503 ADD_TEST(set_private_key); 504 ADD_TEST(decoded_flag_test); 505 ADD_ALL_TESTS(ecpkparams_i2d2i_test, crv_len); 506 507 return 1; 508} 509 510void cleanup_tests(void) 511{ 512 OPENSSL_free(curves); 513} 514