diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/libcrypto/ec/ec_key.c | 139 |
1 files changed, 80 insertions, 59 deletions
diff --git a/src/lib/libcrypto/ec/ec_key.c b/src/lib/libcrypto/ec/ec_key.c index bad4779ed1..2ef5d75d47 100644 --- a/src/lib/libcrypto/ec/ec_key.c +++ b/src/lib/libcrypto/ec/ec_key.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: ec_key.c,v 1.29 2022/11/26 16:08:52 tb Exp $ */ | 1 | /* $OpenBSD: ec_key.c,v 1.30 2023/01/14 15:10:45 jsing Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Written by Nils Larsch for the OpenSSL project. | 3 | * Written by Nils Larsch for the OpenSSL project. |
| 4 | */ | 4 | */ |
| @@ -259,84 +259,93 @@ EC_KEY_generate_key(EC_KEY *eckey) | |||
| 259 | int | 259 | int |
| 260 | ossl_ec_key_gen(EC_KEY *eckey) | 260 | ossl_ec_key_gen(EC_KEY *eckey) |
| 261 | { | 261 | { |
| 262 | int ok = 0; | ||
| 263 | BN_CTX *ctx = NULL; | 262 | BN_CTX *ctx = NULL; |
| 264 | BIGNUM *priv_key = NULL, *order = NULL; | 263 | BIGNUM *priv_key = NULL; |
| 265 | EC_POINT *pub_key = NULL; | 264 | EC_POINT *pub_key = NULL; |
| 265 | BIGNUM *order; | ||
| 266 | int ret = 0; | ||
| 266 | 267 | ||
| 267 | if (!eckey || !eckey->group) { | 268 | if (eckey == NULL || eckey->group == NULL) { |
| 268 | ECerror(ERR_R_PASSED_NULL_PARAMETER); | 269 | ECerror(ERR_R_PASSED_NULL_PARAMETER); |
| 269 | return 0; | 270 | goto err; |
| 270 | } | 271 | } |
| 271 | 272 | ||
| 272 | if ((order = BN_new()) == NULL) | 273 | if ((priv_key = BN_new()) == NULL) |
| 273 | goto err; | 274 | goto err; |
| 275 | if ((pub_key = EC_POINT_new(eckey->group)) == NULL) | ||
| 276 | goto err; | ||
| 277 | |||
| 274 | if ((ctx = BN_CTX_new()) == NULL) | 278 | if ((ctx = BN_CTX_new()) == NULL) |
| 275 | goto err; | 279 | goto err; |
| 276 | 280 | ||
| 277 | if ((priv_key = eckey->priv_key) == NULL) { | 281 | BN_CTX_start(ctx); |
| 278 | if ((priv_key = BN_new()) == NULL) | ||
| 279 | goto err; | ||
| 280 | } | ||
| 281 | 282 | ||
| 282 | if (!EC_GROUP_get_order(eckey->group, order, ctx)) | 283 | if ((order = BN_CTX_get(ctx)) == NULL) |
| 283 | goto err; | 284 | goto err; |
| 284 | 285 | ||
| 286 | if (!EC_GROUP_get_order(eckey->group, order, ctx)) | ||
| 287 | goto err; | ||
| 285 | if (!bn_rand_interval(priv_key, BN_value_one(), order)) | 288 | if (!bn_rand_interval(priv_key, BN_value_one(), order)) |
| 286 | goto err; | 289 | goto err; |
| 287 | |||
| 288 | if ((pub_key = eckey->pub_key) == NULL) { | ||
| 289 | if ((pub_key = EC_POINT_new(eckey->group)) == NULL) | ||
| 290 | goto err; | ||
| 291 | } | ||
| 292 | |||
| 293 | if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx)) | 290 | if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx)) |
| 294 | goto err; | 291 | goto err; |
| 295 | 292 | ||
| 293 | BN_free(eckey->priv_key); | ||
| 296 | eckey->priv_key = priv_key; | 294 | eckey->priv_key = priv_key; |
| 295 | priv_key = NULL; | ||
| 296 | |||
| 297 | EC_POINT_free(eckey->pub_key); | ||
| 297 | eckey->pub_key = pub_key; | 298 | eckey->pub_key = pub_key; |
| 299 | pub_key = NULL; | ||
| 298 | 300 | ||
| 299 | ok = 1; | 301 | ret = 1; |
| 300 | 302 | ||
| 301 | err: | 303 | err: |
| 302 | BN_free(order); | 304 | EC_POINT_free(pub_key); |
| 303 | if (eckey->pub_key == NULL) | 305 | BN_free(priv_key); |
| 304 | EC_POINT_free(pub_key); | 306 | BN_CTX_end(ctx); |
| 305 | if (eckey->priv_key == NULL) | ||
| 306 | BN_free(priv_key); | ||
| 307 | BN_CTX_free(ctx); | 307 | BN_CTX_free(ctx); |
| 308 | return (ok); | 308 | |
| 309 | return ret; | ||
| 309 | } | 310 | } |
| 310 | 311 | ||
| 311 | int | 312 | int |
| 312 | EC_KEY_check_key(const EC_KEY *eckey) | 313 | EC_KEY_check_key(const EC_KEY *eckey) |
| 313 | { | 314 | { |
| 314 | int ok = 0; | ||
| 315 | BN_CTX *ctx = NULL; | 315 | BN_CTX *ctx = NULL; |
| 316 | const BIGNUM *order = NULL; | ||
| 317 | EC_POINT *point = NULL; | 316 | EC_POINT *point = NULL; |
| 317 | BIGNUM *order; | ||
| 318 | int ret = 0; | ||
| 318 | 319 | ||
| 319 | if (!eckey || !eckey->group || !eckey->pub_key) { | 320 | if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) { |
| 320 | ECerror(ERR_R_PASSED_NULL_PARAMETER); | 321 | ECerror(ERR_R_PASSED_NULL_PARAMETER); |
| 321 | return 0; | 322 | goto err; |
| 322 | } | 323 | } |
| 324 | |||
| 323 | if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key) > 0) { | 325 | if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key) > 0) { |
| 324 | ECerror(EC_R_POINT_AT_INFINITY); | 326 | ECerror(EC_R_POINT_AT_INFINITY); |
| 325 | goto err; | 327 | goto err; |
| 326 | } | 328 | } |
| 329 | |||
| 327 | if ((ctx = BN_CTX_new()) == NULL) | 330 | if ((ctx = BN_CTX_new()) == NULL) |
| 328 | goto err; | 331 | goto err; |
| 332 | |||
| 333 | BN_CTX_start(ctx); | ||
| 334 | |||
| 335 | if ((order = BN_CTX_get(ctx)) == NULL) | ||
| 336 | goto err; | ||
| 337 | |||
| 329 | if ((point = EC_POINT_new(eckey->group)) == NULL) | 338 | if ((point = EC_POINT_new(eckey->group)) == NULL) |
| 330 | goto err; | 339 | goto err; |
| 331 | 340 | ||
| 332 | /* testing whether the pub_key is on the elliptic curve */ | 341 | /* Ensure public key is on the elliptic curve. */ |
| 333 | if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) { | 342 | if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) { |
| 334 | ECerror(EC_R_POINT_IS_NOT_ON_CURVE); | 343 | ECerror(EC_R_POINT_IS_NOT_ON_CURVE); |
| 335 | goto err; | 344 | goto err; |
| 336 | } | 345 | } |
| 337 | /* testing whether pub_key * order is the point at infinity */ | 346 | |
| 338 | order = &eckey->group->order; | 347 | /* Ensure public key multiplied by the order is the point at infinity. */ |
| 339 | if (BN_is_zero(order)) { | 348 | if (!EC_GROUP_get_order(eckey->group, order, ctx)) { |
| 340 | ECerror(EC_R_INVALID_GROUP_ORDER); | 349 | ECerror(EC_R_INVALID_GROUP_ORDER); |
| 341 | goto err; | 350 | goto err; |
| 342 | } | 351 | } |
| @@ -348,84 +357,90 @@ EC_KEY_check_key(const EC_KEY *eckey) | |||
| 348 | ECerror(EC_R_WRONG_ORDER); | 357 | ECerror(EC_R_WRONG_ORDER); |
| 349 | goto err; | 358 | goto err; |
| 350 | } | 359 | } |
| 360 | |||
| 351 | /* | 361 | /* |
| 352 | * in case the priv_key is present : check if generator * priv_key == | 362 | * If the private key is present, ensure that the private key multiplied |
| 353 | * pub_key | 363 | * by the generator matches the public key. |
| 354 | */ | 364 | */ |
| 355 | if (eckey->priv_key) { | 365 | if (eckey->priv_key != NULL) { |
| 356 | if (BN_cmp(eckey->priv_key, order) >= 0) { | 366 | if (BN_cmp(eckey->priv_key, order) >= 0) { |
| 357 | ECerror(EC_R_WRONG_ORDER); | 367 | ECerror(EC_R_WRONG_ORDER); |
| 358 | goto err; | 368 | goto err; |
| 359 | } | 369 | } |
| 360 | if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, | 370 | if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, NULL, |
| 361 | NULL, NULL, ctx)) { | 371 | NULL, ctx)) { |
| 362 | ECerror(ERR_R_EC_LIB); | 372 | ECerror(ERR_R_EC_LIB); |
| 363 | goto err; | 373 | goto err; |
| 364 | } | 374 | } |
| 365 | if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, | 375 | if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, |
| 366 | ctx) != 0) { | 376 | ctx) != 0) { |
| 367 | ECerror(EC_R_INVALID_PRIVATE_KEY); | 377 | ECerror(EC_R_INVALID_PRIVATE_KEY); |
| 368 | goto err; | 378 | goto err; |
| 369 | } | 379 | } |
| 370 | } | 380 | } |
| 371 | ok = 1; | 381 | |
| 382 | ret = 1; | ||
| 383 | |||
| 372 | err: | 384 | err: |
| 385 | BN_CTX_end(ctx); | ||
| 373 | BN_CTX_free(ctx); | 386 | BN_CTX_free(ctx); |
| 374 | EC_POINT_free(point); | 387 | EC_POINT_free(point); |
| 375 | return (ok); | 388 | |
| 389 | return ret; | ||
| 376 | } | 390 | } |
| 377 | 391 | ||
| 378 | int | 392 | int |
| 379 | EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y) | 393 | EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y) |
| 380 | { | 394 | { |
| 381 | BN_CTX *ctx = NULL; | 395 | BN_CTX *ctx = NULL; |
| 382 | BIGNUM *tx, *ty; | ||
| 383 | EC_POINT *point = NULL; | 396 | EC_POINT *point = NULL; |
| 384 | int ok = 0; | 397 | BIGNUM *tx, *ty; |
| 398 | int ret = 0; | ||
| 385 | 399 | ||
| 386 | if (!key || !key->group || !x || !y) { | 400 | if (key == NULL || key->group == NULL || x == NULL || y == NULL) { |
| 387 | ECerror(ERR_R_PASSED_NULL_PARAMETER); | 401 | ECerror(ERR_R_PASSED_NULL_PARAMETER); |
| 388 | return 0; | ||
| 389 | } | ||
| 390 | ctx = BN_CTX_new(); | ||
| 391 | if (!ctx) | ||
| 392 | goto err; | 402 | goto err; |
| 403 | } | ||
| 393 | 404 | ||
| 394 | point = EC_POINT_new(key->group); | 405 | if ((ctx = BN_CTX_new()) == NULL) |
| 395 | |||
| 396 | if (!point) | ||
| 397 | goto err; | 406 | goto err; |
| 398 | 407 | ||
| 408 | BN_CTX_start(ctx); | ||
| 409 | |||
| 399 | if ((tx = BN_CTX_get(ctx)) == NULL) | 410 | if ((tx = BN_CTX_get(ctx)) == NULL) |
| 400 | goto err; | 411 | goto err; |
| 401 | if ((ty = BN_CTX_get(ctx)) == NULL) | 412 | if ((ty = BN_CTX_get(ctx)) == NULL) |
| 402 | goto err; | 413 | goto err; |
| 403 | 414 | ||
| 415 | if ((point = EC_POINT_new(key->group)) == NULL) | ||
| 416 | goto err; | ||
| 417 | |||
| 404 | if (!EC_POINT_set_affine_coordinates(key->group, point, x, y, ctx)) | 418 | if (!EC_POINT_set_affine_coordinates(key->group, point, x, y, ctx)) |
| 405 | goto err; | 419 | goto err; |
| 406 | if (!EC_POINT_get_affine_coordinates(key->group, point, tx, ty, ctx)) | 420 | if (!EC_POINT_get_affine_coordinates(key->group, point, tx, ty, ctx)) |
| 407 | goto err; | 421 | goto err; |
| 422 | |||
| 408 | /* | 423 | /* |
| 409 | * Check if retrieved coordinates match originals: if not values are | 424 | * Check if retrieved coordinates match originals: if not values are |
| 410 | * out of range. | 425 | * out of range. |
| 411 | */ | 426 | */ |
| 412 | if (BN_cmp(x, tx) || BN_cmp(y, ty)) { | 427 | if (BN_cmp(x, tx) != 0 || BN_cmp(y, ty) != 0) { |
| 413 | ECerror(EC_R_COORDINATES_OUT_OF_RANGE); | 428 | ECerror(EC_R_COORDINATES_OUT_OF_RANGE); |
| 414 | goto err; | 429 | goto err; |
| 415 | } | 430 | } |
| 416 | if (!EC_KEY_set_public_key(key, point)) | 431 | if (!EC_KEY_set_public_key(key, point)) |
| 417 | goto err; | 432 | goto err; |
| 418 | |||
| 419 | if (EC_KEY_check_key(key) == 0) | 433 | if (EC_KEY_check_key(key) == 0) |
| 420 | goto err; | 434 | goto err; |
| 421 | 435 | ||
| 422 | ok = 1; | 436 | ret = 1; |
| 423 | 437 | ||
| 424 | err: | 438 | err: |
| 439 | BN_CTX_end(ctx); | ||
| 425 | BN_CTX_free(ctx); | 440 | BN_CTX_free(ctx); |
| 426 | EC_POINT_free(point); | 441 | EC_POINT_free(point); |
| 427 | return ok; | ||
| 428 | 442 | ||
| 443 | return ret; | ||
| 429 | } | 444 | } |
| 430 | 445 | ||
| 431 | const EC_GROUP * | 446 | const EC_GROUP * |
| @@ -457,9 +472,12 @@ EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) | |||
| 457 | if (key->meth->set_private != NULL && | 472 | if (key->meth->set_private != NULL && |
| 458 | key->meth->set_private(key, priv_key) == 0) | 473 | key->meth->set_private(key, priv_key) == 0) |
| 459 | return 0; | 474 | return 0; |
| 460 | BN_clear_free(key->priv_key); | 475 | |
| 461 | key->priv_key = BN_dup(priv_key); | 476 | BN_free(key->priv_key); |
| 462 | return (key->priv_key == NULL) ? 0 : 1; | 477 | if ((key->priv_key = BN_dup(priv_key)) == NULL) |
| 478 | return 0; | ||
| 479 | |||
| 480 | return 1; | ||
| 463 | } | 481 | } |
| 464 | 482 | ||
| 465 | const EC_POINT * | 483 | const EC_POINT * |
| @@ -474,9 +492,12 @@ EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) | |||
| 474 | if (key->meth->set_public != NULL && | 492 | if (key->meth->set_public != NULL && |
| 475 | key->meth->set_public(key, pub_key) == 0) | 493 | key->meth->set_public(key, pub_key) == 0) |
| 476 | return 0; | 494 | return 0; |
| 495 | |||
| 477 | EC_POINT_free(key->pub_key); | 496 | EC_POINT_free(key->pub_key); |
| 478 | key->pub_key = EC_POINT_dup(pub_key, key->group); | 497 | if ((key->pub_key = EC_POINT_dup(pub_key, key->group)) == NULL) |
| 479 | return (key->pub_key == NULL) ? 0 : 1; | 498 | return 0; |
| 499 | |||
| 500 | return 1; | ||
| 480 | } | 501 | } |
| 481 | 502 | ||
| 482 | unsigned int | 503 | unsigned int |
