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 21 static size_t crv_len = 0; 22 static EC_builtin_curve *curves = NULL; 23 24 /* sanity checks field_inv function pointer in EC_METHOD */ 25 static 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 */ 75 static 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 */ 108 static 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 */ 125 static 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 */ 142 static 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 */ 150 static 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 EC_GF2m_simple_method directly */ 159 static int field_tests_ec2_simple(void) 160 { 161 TEST_info("Testing EC_GF2m_simple_method()\n"); 162 return field_tests(EC_GF2m_simple_method(), params_b283, 163 sizeof(params_b283) / 3); 164 } 165 #endif 166 167 /* test default method for a named curve */ 168 static int field_tests_default(int n) 169 { 170 BN_CTX *ctx = NULL; 171 EC_GROUP *group = NULL; 172 int nid = curves[n].nid; 173 int ret = 0; 174 175 TEST_info("Testing curve %s\n", OBJ_nid2sn(nid)); 176 177 if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(nid)) 178 || !TEST_ptr(ctx = BN_CTX_new()) 179 || !group_field_tests(group, ctx)) 180 goto err; 181 182 ret = 1; 183 err: 184 if (group != NULL) 185 EC_GROUP_free(group); 186 if (ctx != NULL) 187 BN_CTX_free(ctx); 188 return ret; 189 } 190 191 #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 192 /* 193 * Tests a point known to cause an incorrect underflow in an old version of 194 * ecp_nist521.c 195 */ 196 static int underflow_test(void) 197 { 198 BN_CTX *ctx = NULL; 199 EC_GROUP *grp = NULL; 200 EC_POINT *P = NULL, *Q = NULL, *R = NULL; 201 BIGNUM *x1 = NULL, *y1 = NULL, *z1 = NULL, *x2 = NULL, *y2 = NULL; 202 BIGNUM *k = NULL; 203 int testresult = 0; 204 const char *x1str = 205 "1534f0077fffffe87e9adcfe000000000000000000003e05a21d2400002e031b1f4" 206 "b80000c6fafa4f3c1288798d624a247b5e2ffffffffffffffefe099241900004"; 207 const char *p521m1 = 208 "1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" 209 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"; 210 211 ctx = BN_CTX_new(); 212 if (!TEST_ptr(ctx)) 213 return 0; 214 215 BN_CTX_start(ctx); 216 x1 = BN_CTX_get(ctx); 217 y1 = BN_CTX_get(ctx); 218 z1 = BN_CTX_get(ctx); 219 x2 = BN_CTX_get(ctx); 220 y2 = BN_CTX_get(ctx); 221 k = BN_CTX_get(ctx); 222 if (!TEST_ptr(k)) 223 goto err; 224 225 grp = EC_GROUP_new_by_curve_name(NID_secp521r1); 226 P = EC_POINT_new(grp); 227 Q = EC_POINT_new(grp); 228 R = EC_POINT_new(grp); 229 if (!TEST_ptr(grp) || !TEST_ptr(P) || !TEST_ptr(Q) || !TEST_ptr(R)) 230 goto err; 231 232 if (!TEST_int_gt(BN_hex2bn(&x1, x1str), 0) 233 || !TEST_int_gt(BN_hex2bn(&y1, p521m1), 0) 234 || !TEST_int_gt(BN_hex2bn(&z1, p521m1), 0) 235 || !TEST_int_gt(BN_hex2bn(&k, "02"), 0) 236 || !TEST_true(ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(grp, P, x1, 237 y1, z1, ctx)) 238 || !TEST_true(EC_POINT_mul(grp, Q, NULL, P, k, ctx)) 239 || !TEST_true(EC_POINT_get_affine_coordinates(grp, Q, x1, y1, ctx)) 240 || !TEST_true(EC_POINT_dbl(grp, R, P, ctx)) 241 || !TEST_true(EC_POINT_get_affine_coordinates(grp, R, x2, y2, ctx))) 242 goto err; 243 244 if (!TEST_int_eq(BN_cmp(x1, x2), 0) 245 || !TEST_int_eq(BN_cmp(y1, y2), 0)) 246 goto err; 247 248 testresult = 1; 249 250 err: 251 BN_CTX_end(ctx); 252 EC_POINT_free(P); 253 EC_POINT_free(Q); 254 EC_POINT_free(R); 255 EC_GROUP_free(grp); 256 BN_CTX_free(ctx); 257 258 return testresult; 259 } 260 #endif 261 262 /* 263 * Tests behavior of the EC_KEY_set_private_key 264 */ 265 static int set_private_key(void) 266 { 267 EC_KEY *key = NULL, *aux_key = NULL; 268 int testresult = 0; 269 270 key = EC_KEY_new_by_curve_name(NID_secp224r1); 271 aux_key = EC_KEY_new_by_curve_name(NID_secp224r1); 272 if (!TEST_ptr(key) 273 || !TEST_ptr(aux_key) 274 || !TEST_int_eq(EC_KEY_generate_key(key), 1) 275 || !TEST_int_eq(EC_KEY_generate_key(aux_key), 1)) 276 goto err; 277 278 /* Test setting a valid private key */ 279 if (!TEST_int_eq(EC_KEY_set_private_key(key, aux_key->priv_key), 1)) 280 goto err; 281 282 /* Test compliance with legacy behavior for NULL private keys */ 283 if (!TEST_int_eq(EC_KEY_set_private_key(key, NULL), 0) 284 || !TEST_ptr_null(key->priv_key)) 285 goto err; 286 287 testresult = 1; 288 289 err: 290 EC_KEY_free(key); 291 EC_KEY_free(aux_key); 292 return testresult; 293 } 294 295 /* 296 * Tests behavior of the decoded_from_explicit_params flag and API 297 */ 298 static int decoded_flag_test(void) 299 { 300 EC_GROUP *grp; 301 EC_GROUP *grp_copy = NULL; 302 ECPARAMETERS *ecparams = NULL; 303 ECPKPARAMETERS *ecpkparams = NULL; 304 EC_KEY *key = NULL; 305 unsigned char *encodedparams = NULL; 306 const unsigned char *encp; 307 int encodedlen; 308 int testresult = 0; 309 310 /* Test EC_GROUP_new not setting the flag */ 311 grp = EC_GROUP_new(EC_GFp_simple_method()); 312 if (!TEST_ptr(grp) 313 || !TEST_int_eq(grp->decoded_from_explicit_params, 0)) 314 goto err; 315 EC_GROUP_free(grp); 316 317 /* Test EC_GROUP_new_by_curve_name not setting the flag */ 318 grp = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); 319 if (!TEST_ptr(grp) 320 || !TEST_int_eq(grp->decoded_from_explicit_params, 0)) 321 goto err; 322 323 /* Test EC_GROUP_new_from_ecparameters not setting the flag */ 324 if (!TEST_ptr(ecparams = EC_GROUP_get_ecparameters(grp, NULL)) 325 || !TEST_ptr(grp_copy = EC_GROUP_new_from_ecparameters(ecparams)) 326 || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0)) 327 goto err; 328 EC_GROUP_free(grp_copy); 329 grp_copy = NULL; 330 ECPARAMETERS_free(ecparams); 331 ecparams = NULL; 332 333 /* Test EC_GROUP_new_from_ecpkparameters not setting the flag */ 334 if (!TEST_int_eq(EC_GROUP_get_asn1_flag(grp), OPENSSL_EC_NAMED_CURVE) 335 || !TEST_ptr(ecpkparams = EC_GROUP_get_ecpkparameters(grp, NULL)) 336 || !TEST_ptr(grp_copy = EC_GROUP_new_from_ecpkparameters(ecpkparams)) 337 || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0) 338 || !TEST_ptr(key = EC_KEY_new()) 339 /* Test EC_KEY_decoded_from_explicit_params on key without a group */ 340 || !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), -1) 341 || !TEST_int_eq(EC_KEY_set_group(key, grp_copy), 1) 342 /* Test EC_KEY_decoded_from_explicit_params negative case */ 343 || !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), 0)) 344 goto err; 345 EC_GROUP_free(grp_copy); 346 grp_copy = NULL; 347 ECPKPARAMETERS_free(ecpkparams); 348 ecpkparams = NULL; 349 350 /* Test d2i_ECPKParameters with named params not setting the flag */ 351 if (!TEST_int_gt(encodedlen = i2d_ECPKParameters(grp, &encodedparams), 0) 352 || !TEST_ptr(encp = encodedparams) 353 || !TEST_ptr(grp_copy = d2i_ECPKParameters(NULL, &encp, encodedlen)) 354 || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0)) 355 goto err; 356 EC_GROUP_free(grp_copy); 357 grp_copy = NULL; 358 OPENSSL_free(encodedparams); 359 encodedparams = NULL; 360 361 /* Asn1 flag stays set to explicit with EC_GROUP_new_from_ecpkparameters */ 362 EC_GROUP_set_asn1_flag(grp, OPENSSL_EC_EXPLICIT_CURVE); 363 if (!TEST_ptr(ecpkparams = EC_GROUP_get_ecpkparameters(grp, NULL)) 364 || !TEST_ptr(grp_copy = EC_GROUP_new_from_ecpkparameters(ecpkparams)) 365 || !TEST_int_eq(EC_GROUP_get_asn1_flag(grp_copy), OPENSSL_EC_EXPLICIT_CURVE) 366 || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0)) 367 goto err; 368 EC_GROUP_free(grp_copy); 369 grp_copy = NULL; 370 371 /* Test d2i_ECPKParameters with explicit params setting the flag */ 372 if (!TEST_int_gt(encodedlen = i2d_ECPKParameters(grp, &encodedparams), 0) 373 || !TEST_ptr(encp = encodedparams) 374 || !TEST_ptr(grp_copy = d2i_ECPKParameters(NULL, &encp, encodedlen)) 375 || !TEST_int_eq(EC_GROUP_get_asn1_flag(grp_copy), OPENSSL_EC_EXPLICIT_CURVE) 376 || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 1) 377 || !TEST_int_eq(EC_KEY_set_group(key, grp_copy), 1) 378 /* Test EC_KEY_decoded_from_explicit_params positive case */ 379 || !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), 1)) 380 goto err; 381 382 testresult = 1; 383 384 err: 385 EC_KEY_free(key); 386 EC_GROUP_free(grp); 387 EC_GROUP_free(grp_copy); 388 ECPARAMETERS_free(ecparams); 389 ECPKPARAMETERS_free(ecpkparams); 390 OPENSSL_free(encodedparams); 391 392 return testresult; 393 } 394 395 static 396 int ecpkparams_i2d2i_test(int n) 397 { 398 EC_GROUP *g1 = NULL, *g2 = NULL; 399 FILE *fp = NULL; 400 int nid = curves[n].nid; 401 int testresult = 0; 402 403 /* create group */ 404 if (!TEST_ptr(g1 = EC_GROUP_new_by_curve_name(nid))) 405 goto end; 406 407 /* encode params to file */ 408 if (!TEST_ptr(fp = fopen("params.der", "wb")) 409 || !TEST_true(i2d_ECPKParameters_fp(fp, g1))) 410 goto end; 411 412 /* flush and close file */ 413 if (!TEST_int_eq(fclose(fp), 0)) { 414 fp = NULL; 415 goto end; 416 } 417 fp = NULL; 418 419 /* decode params from file */ 420 if (!TEST_ptr(fp = fopen("params.der", "rb")) 421 || !TEST_ptr(g2 = d2i_ECPKParameters_fp(fp, NULL))) 422 goto end; 423 424 testresult = 1; /* PASS */ 425 426 end: 427 if (fp != NULL) 428 fclose(fp); 429 430 EC_GROUP_free(g1); 431 EC_GROUP_free(g2); 432 433 return testresult; 434 } 435 436 int setup_tests(void) 437 { 438 crv_len = EC_get_builtin_curves(NULL, 0); 439 if (!TEST_ptr(curves = OPENSSL_malloc(sizeof(*curves) * crv_len)) 440 || !TEST_true(EC_get_builtin_curves(curves, crv_len))) 441 return 0; 442 443 ADD_TEST(field_tests_ecp_simple); 444 ADD_TEST(field_tests_ecp_mont); 445 #ifndef OPENSSL_NO_EC2M 446 ADD_TEST(field_tests_ec2_simple); 447 #endif 448 ADD_ALL_TESTS(field_tests_default, crv_len); 449 #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 450 ADD_TEST(underflow_test); 451 #endif 452 ADD_TEST(set_private_key); 453 ADD_TEST(decoded_flag_test); 454 ADD_ALL_TESTS(ecpkparams_i2d2i_test, crv_len); 455 456 return 1; 457 } 458 459 void cleanup_tests(void) 460 { 461 OPENSSL_free(curves); 462 } 463