summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/ec/ecp_methods.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/ec/ecp_methods.c')
-rw-r--r--src/lib/libcrypto/ec/ecp_methods.c177
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
182static int 182static int
183ec_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
191static int
192ec_point_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
193{
194 return BN_is_zero(point->Z);
195}
196
197static int
183ec_point_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx) 198ec_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
291static int
292ec_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
275ec_point_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, 349ec_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,
1281static const EC_METHOD ec_GFp_simple_method = { 1334static 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)
1304static const EC_METHOD ec_GFp_mont_method = { 1359static 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,