diff options
Diffstat (limited to 'src/lib/libcrypto/ec/ecp_methods.c')
| -rw-r--r-- | src/lib/libcrypto/ec/ecp_methods.c | 177 |
1 files changed, 117 insertions, 60 deletions
diff --git a/src/lib/libcrypto/ec/ecp_methods.c b/src/lib/libcrypto/ec/ecp_methods.c index ced85ceb1e..8fa78924d2 100644 --- a/src/lib/libcrypto/ec/ecp_methods.c +++ b/src/lib/libcrypto/ec/ecp_methods.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: ecp_methods.c,v 1.45 2025/03/24 13:07:04 jsing Exp $ */ | 1 | /* $OpenBSD: ecp_methods.c,v 1.48 2026/01/18 10:07:44 tb Exp $ */ |
| 2 | /* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de> | 2 | /* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de> |
| 3 | * for the OpenSSL project. | 3 | * for the OpenSSL project. |
| 4 | * Includes code written by Bodo Moeller for the OpenSSL project. | 4 | * Includes code written by Bodo Moeller for the OpenSSL project. |
| @@ -66,11 +66,11 @@ | |||
| 66 | 66 | ||
| 67 | #include <openssl/bn.h> | 67 | #include <openssl/bn.h> |
| 68 | #include <openssl/ec.h> | 68 | #include <openssl/ec.h> |
| 69 | #include <openssl/err.h> | ||
| 70 | #include <openssl/objects.h> | 69 | #include <openssl/objects.h> |
| 71 | 70 | ||
| 72 | #include "bn_local.h" | 71 | #include "bn_local.h" |
| 73 | #include "ec_local.h" | 72 | #include "ec_local.h" |
| 73 | #include "err_local.h" | ||
| 74 | 74 | ||
| 75 | /* | 75 | /* |
| 76 | * Most method functions in this file are designed to work with non-trivial | 76 | * Most method functions in this file are designed to work with non-trivial |
| @@ -180,6 +180,21 @@ ec_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, | |||
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | static int | 182 | static int |
| 183 | ec_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point) | ||
| 184 | { | ||
| 185 | BN_zero(point->Z); | ||
| 186 | point->Z_is_one = 0; | ||
| 187 | |||
| 188 | return 1; | ||
| 189 | } | ||
| 190 | |||
| 191 | static int | ||
| 192 | ec_point_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) | ||
| 193 | { | ||
| 194 | return BN_is_zero(point->Z); | ||
| 195 | } | ||
| 196 | |||
| 197 | static int | ||
| 183 | ec_point_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx) | 198 | ec_point_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx) |
| 184 | { | 199 | { |
| 185 | BIGNUM *rh, *tmp, *Z4, *Z6; | 200 | BIGNUM *rh, *tmp, *Z4, *Z6; |
| @@ -268,6 +283,65 @@ ec_point_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx) | |||
| 268 | } | 283 | } |
| 269 | 284 | ||
| 270 | /* | 285 | /* |
| 286 | * Compare a and b under the assumption that exactly one of them is affine. | ||
| 287 | * This avoids needless multiplications by one, which are expensive in the | ||
| 288 | * Montgomery domain. | ||
| 289 | */ | ||
| 290 | |||
| 291 | static int | ||
| 292 | ec_point_cmp_one_affine(const EC_GROUP *group, const EC_POINT *a, | ||
| 293 | const EC_POINT *b, BN_CTX *ctx) | ||
| 294 | { | ||
| 295 | const EC_POINT *tmp; | ||
| 296 | BIGNUM *az, *bn; | ||
| 297 | int ret = -1; | ||
| 298 | |||
| 299 | BN_CTX_start(ctx); | ||
| 300 | |||
| 301 | if (a->Z_is_one == b->Z_is_one) | ||
| 302 | goto err; | ||
| 303 | |||
| 304 | /* Ensure b is the affine point. */ | ||
| 305 | if (a->Z_is_one) { | ||
| 306 | tmp = a; | ||
| 307 | a = b; | ||
| 308 | b = tmp; | ||
| 309 | } | ||
| 310 | |||
| 311 | if ((az = BN_CTX_get(ctx)) == NULL) | ||
| 312 | goto err; | ||
| 313 | if ((bn = BN_CTX_get(ctx)) == NULL) | ||
| 314 | goto err; | ||
| 315 | |||
| 316 | /* a->X == b->X * a->Z^2 ? */ | ||
| 317 | if (!ec_field_sqr(group, az, a->Z, ctx)) | ||
| 318 | goto err; | ||
| 319 | if (!ec_field_mul(group, bn, b->X, az, ctx)) | ||
| 320 | goto err; | ||
| 321 | if (BN_cmp(a->X, bn) != 0) { | ||
| 322 | ret = 1; | ||
| 323 | goto err; | ||
| 324 | } | ||
| 325 | |||
| 326 | /* a->Y == b->Y * a->Z^3 ? */ | ||
| 327 | if (!ec_field_mul(group, az, az, a->Z, ctx)) | ||
| 328 | goto err; | ||
| 329 | if (!ec_field_mul(group, bn, b->Y, az, ctx)) | ||
| 330 | goto err; | ||
| 331 | if (BN_cmp(a->Y, bn) != 0) { | ||
| 332 | ret = 1; | ||
| 333 | goto err; | ||
| 334 | } | ||
| 335 | |||
| 336 | ret = 0; | ||
| 337 | |||
| 338 | err: | ||
| 339 | BN_CTX_end(ctx); | ||
| 340 | |||
| 341 | return ret; | ||
| 342 | } | ||
| 343 | |||
| 344 | /* | ||
| 271 | * Returns -1 on error, 0 if the points are equal, 1 if the points are distinct. | 345 | * Returns -1 on error, 0 if the points are equal, 1 if the points are distinct. |
| 272 | */ | 346 | */ |
| 273 | 347 | ||
| @@ -275,8 +349,7 @@ static int | |||
| 275 | ec_point_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, | 349 | ec_point_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, |
| 276 | BN_CTX *ctx) | 350 | BN_CTX *ctx) |
| 277 | { | 351 | { |
| 278 | BIGNUM *tmp1, *tmp2, *Za23, *Zb23; | 352 | BIGNUM *az, *bz, *bn1, *bn2; |
| 279 | const BIGNUM *tmp1_, *tmp2_; | ||
| 280 | int ret = -1; | 353 | int ret = -1; |
| 281 | 354 | ||
| 282 | if (EC_POINT_is_at_infinity(group, a) && EC_POINT_is_at_infinity(group, b)) | 355 | if (EC_POINT_is_at_infinity(group, a) && EC_POINT_is_at_infinity(group, b)) |
| @@ -286,71 +359,51 @@ ec_point_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, | |||
| 286 | 359 | ||
| 287 | if (a->Z_is_one && b->Z_is_one) | 360 | if (a->Z_is_one && b->Z_is_one) |
| 288 | return BN_cmp(a->X, b->X) != 0 || BN_cmp(a->Y, b->Y) != 0; | 361 | return BN_cmp(a->X, b->X) != 0 || BN_cmp(a->Y, b->Y) != 0; |
| 362 | if (a->Z_is_one || b->Z_is_one) | ||
| 363 | return ec_point_cmp_one_affine(group, a, b, ctx); | ||
| 289 | 364 | ||
| 290 | BN_CTX_start(ctx); | 365 | BN_CTX_start(ctx); |
| 291 | 366 | ||
| 292 | if ((tmp1 = BN_CTX_get(ctx)) == NULL) | 367 | if ((az = BN_CTX_get(ctx)) == NULL) |
| 293 | goto end; | 368 | goto err; |
| 294 | if ((tmp2 = BN_CTX_get(ctx)) == NULL) | 369 | if ((bz = BN_CTX_get(ctx)) == NULL) |
| 295 | goto end; | 370 | goto err; |
| 296 | if ((Za23 = BN_CTX_get(ctx)) == NULL) | 371 | if ((bn1 = BN_CTX_get(ctx)) == NULL) |
| 297 | goto end; | 372 | goto err; |
| 298 | if ((Zb23 = BN_CTX_get(ctx)) == NULL) | 373 | if ((bn2 = BN_CTX_get(ctx)) == NULL) |
| 299 | goto end; | 374 | goto err; |
| 300 | |||
| 301 | /* | ||
| 302 | * Decide whether (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3), or | ||
| 303 | * equivalently, (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3). | ||
| 304 | */ | ||
| 305 | |||
| 306 | if (!b->Z_is_one) { | ||
| 307 | if (!ec_field_sqr(group, Zb23, b->Z, ctx)) | ||
| 308 | goto end; | ||
| 309 | if (!ec_field_mul(group, tmp1, a->X, Zb23, ctx)) | ||
| 310 | goto end; | ||
| 311 | tmp1_ = tmp1; | ||
| 312 | } else | ||
| 313 | tmp1_ = a->X; | ||
| 314 | if (!a->Z_is_one) { | ||
| 315 | if (!ec_field_sqr(group, Za23, a->Z, ctx)) | ||
| 316 | goto end; | ||
| 317 | if (!ec_field_mul(group, tmp2, b->X, Za23, ctx)) | ||
| 318 | goto end; | ||
| 319 | tmp2_ = tmp2; | ||
| 320 | } else | ||
| 321 | tmp2_ = b->X; | ||
| 322 | 375 | ||
| 323 | /* compare X_a*Z_b^2 with X_b*Z_a^2 */ | 376 | /* a->X * b->Z^2 == b->X * a->Z^2 ? */ |
| 324 | if (BN_cmp(tmp1_, tmp2_) != 0) { | 377 | if (!ec_field_sqr(group, bz, b->Z, ctx)) |
| 325 | ret = 1; /* points differ */ | 378 | goto err; |
| 326 | goto end; | 379 | if (!ec_field_mul(group, bn1, a->X, bz, ctx)) |
| 380 | goto err; | ||
| 381 | if (!ec_field_sqr(group, az, a->Z, ctx)) | ||
| 382 | goto err; | ||
| 383 | if (!ec_field_mul(group, bn2, b->X, az, ctx)) | ||
| 384 | goto err; | ||
| 385 | if (BN_cmp(bn1, bn2) != 0) { | ||
| 386 | ret = 1; | ||
| 387 | goto err; | ||
| 327 | } | 388 | } |
| 328 | if (!b->Z_is_one) { | ||
| 329 | if (!ec_field_mul(group, Zb23, Zb23, b->Z, ctx)) | ||
| 330 | goto end; | ||
| 331 | if (!ec_field_mul(group, tmp1, a->Y, Zb23, ctx)) | ||
| 332 | goto end; | ||
| 333 | /* tmp1_ = tmp1 */ | ||
| 334 | } else | ||
| 335 | tmp1_ = a->Y; | ||
| 336 | if (!a->Z_is_one) { | ||
| 337 | if (!ec_field_mul(group, Za23, Za23, a->Z, ctx)) | ||
| 338 | goto end; | ||
| 339 | if (!ec_field_mul(group, tmp2, b->Y, Za23, ctx)) | ||
| 340 | goto end; | ||
| 341 | /* tmp2_ = tmp2 */ | ||
| 342 | } else | ||
| 343 | tmp2_ = b->Y; | ||
| 344 | 389 | ||
| 345 | /* compare Y_a*Z_b^3 with Y_b*Z_a^3 */ | 390 | /* a->Y * b->Z^3 == b->Y * a->Z^3 ? */ |
| 346 | if (BN_cmp(tmp1_, tmp2_) != 0) { | 391 | if (!ec_field_mul(group, bz, bz, b->Z, ctx)) |
| 347 | ret = 1; /* points differ */ | 392 | goto err; |
| 348 | goto end; | 393 | if (!ec_field_mul(group, bn1, a->Y, bz, ctx)) |
| 394 | goto err; | ||
| 395 | if (!ec_field_mul(group, az, az, a->Z, ctx)) | ||
| 396 | goto err; | ||
| 397 | if (!ec_field_mul(group, bn2, b->Y, az, ctx)) | ||
| 398 | goto err; | ||
| 399 | if (BN_cmp(bn1, bn2) != 0) { | ||
| 400 | ret = 1; | ||
| 401 | goto err; | ||
| 349 | } | 402 | } |
| 350 | /* points are equal */ | 403 | |
| 351 | ret = 0; | 404 | ret = 0; |
| 352 | 405 | ||
| 353 | end: | 406 | err: |
| 354 | BN_CTX_end(ctx); | 407 | BN_CTX_end(ctx); |
| 355 | 408 | ||
| 356 | return ret; | 409 | return ret; |
| @@ -1281,6 +1334,8 @@ ec_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, | |||
| 1281 | static const EC_METHOD ec_GFp_simple_method = { | 1334 | static const EC_METHOD ec_GFp_simple_method = { |
| 1282 | .group_set_curve = ec_group_set_curve, | 1335 | .group_set_curve = ec_group_set_curve, |
| 1283 | .group_get_curve = ec_group_get_curve, | 1336 | .group_get_curve = ec_group_get_curve, |
| 1337 | .point_set_to_infinity = ec_point_set_to_infinity, | ||
| 1338 | .point_is_at_infinity = ec_point_is_at_infinity, | ||
| 1284 | .point_is_on_curve = ec_point_is_on_curve, | 1339 | .point_is_on_curve = ec_point_is_on_curve, |
| 1285 | .point_cmp = ec_point_cmp, | 1340 | .point_cmp = ec_point_cmp, |
| 1286 | .point_set_affine_coordinates = ec_point_set_affine_coordinates, | 1341 | .point_set_affine_coordinates = ec_point_set_affine_coordinates, |
| @@ -1304,6 +1359,8 @@ EC_GFp_simple_method(void) | |||
| 1304 | static const EC_METHOD ec_GFp_mont_method = { | 1359 | static const EC_METHOD ec_GFp_mont_method = { |
| 1305 | .group_set_curve = ec_mont_group_set_curve, | 1360 | .group_set_curve = ec_mont_group_set_curve, |
| 1306 | .group_get_curve = ec_group_get_curve, | 1361 | .group_get_curve = ec_group_get_curve, |
| 1362 | .point_set_to_infinity = ec_point_set_to_infinity, | ||
| 1363 | .point_is_at_infinity = ec_point_is_at_infinity, | ||
| 1307 | .point_is_on_curve = ec_point_is_on_curve, | 1364 | .point_is_on_curve = ec_point_is_on_curve, |
| 1308 | .point_cmp = ec_point_cmp, | 1365 | .point_cmp = ec_point_cmp, |
| 1309 | .point_set_affine_coordinates = ec_point_set_affine_coordinates, | 1366 | .point_set_affine_coordinates = ec_point_set_affine_coordinates, |
