summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/ec
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/ec')
-rw-r--r--src/lib/libcrypto/ec/ec_ameth.c4
-rw-r--r--src/lib/libcrypto/ec/ec_asn1.c4
-rw-r--r--src/lib/libcrypto/ec/ec_convert.c8
-rw-r--r--src/lib/libcrypto/ec/ec_curve.c321
-rw-r--r--src/lib/libcrypto/ec/ec_field.c202
-rw-r--r--src/lib/libcrypto/ec/ec_internal.h65
-rw-r--r--src/lib/libcrypto/ec/ec_key.c4
-rw-r--r--src/lib/libcrypto/ec/ec_lib.c63
-rw-r--r--src/lib/libcrypto/ec/ec_local.h22
-rw-r--r--src/lib/libcrypto/ec/ec_mult.c78
-rw-r--r--src/lib/libcrypto/ec/ec_pmeth.c4
-rw-r--r--src/lib/libcrypto/ec/eck_prn.c4
-rw-r--r--src/lib/libcrypto/ec/ecp_hp_methods.c943
-rw-r--r--src/lib/libcrypto/ec/ecp_methods.c23
-rw-r--r--src/lib/libcrypto/ec/ecx_methods.c4
15 files changed, 1399 insertions, 350 deletions
diff --git a/src/lib/libcrypto/ec/ec_ameth.c b/src/lib/libcrypto/ec/ec_ameth.c
index 903b18a8db..ddc8adea1e 100644
--- a/src/lib/libcrypto/ec/ec_ameth.c
+++ b/src/lib/libcrypto/ec/ec_ameth.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec_ameth.c,v 1.73 2024/11/25 06:51:39 tb Exp $ */ 1/* $OpenBSD: ec_ameth.c,v 1.74 2025/05/10 05:54:38 tb Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2006. 3 * project 2006.
4 */ 4 */
@@ -66,7 +66,6 @@
66#include <openssl/bn.h> 66#include <openssl/bn.h>
67#include <openssl/cms.h> 67#include <openssl/cms.h>
68#include <openssl/ec.h> 68#include <openssl/ec.h>
69#include <openssl/err.h>
70#include <openssl/evp.h> 69#include <openssl/evp.h>
71#include <openssl/pkcs7.h> 70#include <openssl/pkcs7.h>
72#include <openssl/objects.h> 71#include <openssl/objects.h>
@@ -74,6 +73,7 @@
74 73
75#include "asn1_local.h" 74#include "asn1_local.h"
76#include "bn_local.h" 75#include "bn_local.h"
76#include "err_local.h"
77#include "evp_local.h" 77#include "evp_local.h"
78#include "x509_local.h" 78#include "x509_local.h"
79 79
diff --git a/src/lib/libcrypto/ec/ec_asn1.c b/src/lib/libcrypto/ec/ec_asn1.c
index ef318f8d43..35f4f5b0ba 100644
--- a/src/lib/libcrypto/ec/ec_asn1.c
+++ b/src/lib/libcrypto/ec/ec_asn1.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec_asn1.c,v 1.111 2025/03/13 10:31:12 tb Exp $ */ 1/* $OpenBSD: ec_asn1.c,v 1.112 2025/05/10 05:54:38 tb Exp $ */
2/* 2/*
3 * Written by Nils Larsch for the OpenSSL project. 3 * Written by Nils Larsch for the OpenSSL project.
4 */ 4 */
@@ -66,12 +66,12 @@
66#include <openssl/asn1.h> 66#include <openssl/asn1.h>
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/asn1t.h> 69#include <openssl/asn1t.h>
71#include <openssl/objects.h> 70#include <openssl/objects.h>
72 71
73#include "asn1_local.h" 72#include "asn1_local.h"
74#include "ec_local.h" 73#include "ec_local.h"
74#include "err_local.h"
75 75
76int 76int
77EC_GROUP_get_basis_type(const EC_GROUP *group) 77EC_GROUP_get_basis_type(const EC_GROUP *group)
diff --git a/src/lib/libcrypto/ec/ec_convert.c b/src/lib/libcrypto/ec/ec_convert.c
index a18bc49132..3b88bd20ba 100644
--- a/src/lib/libcrypto/ec/ec_convert.c
+++ b/src/lib/libcrypto/ec/ec_convert.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec_convert.c,v 1.14 2025/01/05 16:07:08 tb Exp $ */ 1/* $OpenBSD: ec_convert.c,v 1.16 2025/12/26 18:44:19 tb Exp $ */
2/* 2/*
3 * Originally written by Bodo Moeller for the OpenSSL project. 3 * Originally written by Bodo Moeller for the OpenSSL project.
4 */ 4 */
@@ -64,10 +64,10 @@
64#include <string.h> 64#include <string.h>
65 65
66#include <openssl/asn1.h> 66#include <openssl/asn1.h>
67#include <openssl/err.h>
68 67
69#include "asn1_local.h" 68#include "asn1_local.h"
70#include "ec_local.h" 69#include "ec_local.h"
70#include "err_local.h"
71 71
72/* 72/*
73 * Internal handling of the point conversion octet 73 * Internal handling of the point conversion octet
@@ -452,7 +452,7 @@ EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point,
452 if (ctx == NULL) 452 if (ctx == NULL)
453 goto err; 453 goto err;
454 454
455 if (group->meth != point->meth) { 455 if (!ec_group_and_point_compatible(group, point)) {
456 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 456 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
457 goto err; 457 goto err;
458 } 458 }
@@ -478,7 +478,7 @@ EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
478 if (ctx == NULL) 478 if (ctx == NULL)
479 goto err; 479 goto err;
480 480
481 if (group->meth != point->meth) { 481 if (!ec_group_and_point_compatible(group, point)) {
482 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 482 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
483 goto err; 483 goto err;
484 } 484 }
diff --git a/src/lib/libcrypto/ec/ec_curve.c b/src/lib/libcrypto/ec/ec_curve.c
index a3ec2de7fb..fda2681704 100644
--- a/src/lib/libcrypto/ec/ec_curve.c
+++ b/src/lib/libcrypto/ec/ec_curve.c
@@ -1,7 +1,4 @@
1/* $OpenBSD: ec_curve.c,v 1.54 2025/03/09 17:53:11 tb Exp $ */ 1/* $OpenBSD: ec_curve.c,v 1.60 2025/12/15 12:09:46 tb Exp $ */
2/*
3 * Written by Nils Larsch for the OpenSSL project.
4 */
5/* ==================================================================== 2/* ====================================================================
6 * Copyright (c) 1998-2010 The OpenSSL Project. All rights reserved. 3 * Copyright (c) 1998-2010 The OpenSSL Project. All rights reserved.
7 * 4 *
@@ -78,10 +75,10 @@
78 75
79#include <openssl/bn.h> 76#include <openssl/bn.h>
80#include <openssl/ec.h> 77#include <openssl/ec.h>
81#include <openssl/err.h>
82#include <openssl/objects.h> 78#include <openssl/objects.h>
83 79
84#include "ec_local.h" 80#include "ec_local.h"
81#include "err_local.h"
85 82
86static const struct { 83static const struct {
87 uint8_t seed[20]; 84 uint8_t seed[20];
@@ -130,6 +127,57 @@ static const struct {
130 127
131static const struct { 128static const struct {
132 uint8_t seed[20]; 129 uint8_t seed[20];
130 uint8_t p[32];
131 uint8_t a[32];
132 uint8_t b[32];
133 uint8_t x[32];
134 uint8_t y[32];
135 uint8_t order[32];
136} _EC_NIST_PRIME_256 = {
137 .seed = {
138 0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66,
139 0x78, 0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90,
140 },
141 .p = {
142 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
145 0xff, 0xff,
146 },
147 .a = {
148 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
150 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
151 0xff, 0xfc,
152 },
153 .b = {
154 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb,
155 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0,
156 0xcc, 0x53, 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2,
157 0x60, 0x4b,
158 },
159 .x = {
160 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc,
161 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81,
162 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98,
163 0xc2, 0x96,
164 },
165 .y = {
166 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7,
167 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57,
168 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf,
169 0x51, 0xf5,
170 },
171 .order = {
172 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
173 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad,
174 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63,
175 0x25, 0x51,
176 },
177};
178
179static const struct {
180 uint8_t seed[20];
133 uint8_t p[48]; 181 uint8_t p[48];
134 uint8_t a[48]; 182 uint8_t a[48];
135 uint8_t b[48]; 183 uint8_t b[48];
@@ -255,192 +303,6 @@ static const struct {
255}; 303};
256 304
257static const struct { 305static const struct {
258 uint8_t seed[20];
259 uint8_t p[30];
260 uint8_t a[30];
261 uint8_t b[30];
262 uint8_t x[30];
263 uint8_t y[30];
264 uint8_t order[30];
265} _EC_X9_62_PRIME_239V1 = {
266 .seed = {
267 0xe4, 0x3b, 0xb4, 0x60, 0xf0, 0xb8, 0x0c, 0xc0, 0xc0, 0xb0,
268 0x75, 0x79, 0x8e, 0x94, 0x80, 0x60, 0xf8, 0x32, 0x1b, 0x7d,
269 },
270 .p = {
271 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
272 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
273 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
274 },
275 .a = {
276 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
277 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
278 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfc,
279 },
280 .b = {
281 0x6b, 0x01, 0x6c, 0x3b, 0xdc, 0xf1, 0x89, 0x41, 0xd0, 0xd6,
282 0x54, 0x92, 0x14, 0x75, 0xca, 0x71, 0xa9, 0xdb, 0x2f, 0xb2,
283 0x7d, 0x1d, 0x37, 0x79, 0x61, 0x85, 0xc2, 0x94, 0x2c, 0x0a,
284 },
285 .x = {
286 0x0f, 0xfa, 0x96, 0x3c, 0xdc, 0xa8, 0x81, 0x6c, 0xcc, 0x33,
287 0xb8, 0x64, 0x2b, 0xed, 0xf9, 0x05, 0xc3, 0xd3, 0x58, 0x57,
288 0x3d, 0x3f, 0x27, 0xfb, 0xbd, 0x3b, 0x3c, 0xb9, 0xaa, 0xaf,
289 },
290 .y = {
291 0x7d, 0xeb, 0xe8, 0xe4, 0xe9, 0x0a, 0x5d, 0xae, 0x6e, 0x40,
292 0x54, 0xca, 0x53, 0x0b, 0xa0, 0x46, 0x54, 0xb3, 0x68, 0x18,
293 0xce, 0x22, 0x6b, 0x39, 0xfc, 0xcb, 0x7b, 0x02, 0xf1, 0xae,
294 },
295 .order = {
296 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
297 0xff, 0xff, 0x7f, 0xff, 0xff, 0x9e, 0x5e, 0x9a, 0x9f, 0x5d,
298 0x90, 0x71, 0xfb, 0xd1, 0x52, 0x26, 0x88, 0x90, 0x9d, 0x0b,
299 },
300};
301
302static const struct {
303 uint8_t seed[20];
304 uint8_t p[30];
305 uint8_t a[30];
306 uint8_t b[30];
307 uint8_t x[30];
308 uint8_t y[30];
309 uint8_t order[30];
310} _EC_X9_62_PRIME_239V2 = {
311 .seed = {
312 0xe8, 0xb4, 0x01, 0x16, 0x04, 0x09, 0x53, 0x03, 0xca, 0x3b,
313 0x80, 0x99, 0x98, 0x2b, 0xe0, 0x9f, 0xcb, 0x9a, 0xe6, 0x16,
314 },
315 .p = {
316 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
317 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
318 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
319 },
320 .a = {
321 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
322 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
323 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfc,
324 },
325 .b = {
326 0x61, 0x7f, 0xab, 0x68, 0x32, 0x57, 0x6c, 0xbb, 0xfe, 0xd5,
327 0x0d, 0x99, 0xf0, 0x24, 0x9c, 0x3f, 0xee, 0x58, 0xb9, 0x4b,
328 0xa0, 0x03, 0x8c, 0x7a, 0xe8, 0x4c, 0x8c, 0x83, 0x2f, 0x2c,
329 },
330 .x = {
331 0x38, 0xaf, 0x09, 0xd9, 0x87, 0x27, 0x70, 0x51, 0x20, 0xc9,
332 0x21, 0xbb, 0x5e, 0x9e, 0x26, 0x29, 0x6a, 0x3c, 0xdc, 0xf2,
333 0xf3, 0x57, 0x57, 0xa0, 0xea, 0xfd, 0x87, 0xb8, 0x30, 0xe7,
334 },
335 .y = {
336 0x5b, 0x01, 0x25, 0xe4, 0xdb, 0xea, 0x0e, 0xc7, 0x20, 0x6d,
337 0xa0, 0xfc, 0x01, 0xd9, 0xb0, 0x81, 0x32, 0x9f, 0xb5, 0x55,
338 0xde, 0x6e, 0xf4, 0x60, 0x23, 0x7d, 0xff, 0x8b, 0xe4, 0xba,
339 },
340 .order = {
341 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
342 0xff, 0xff, 0x80, 0x00, 0x00, 0xcf, 0xa7, 0xe8, 0x59, 0x43,
343 0x77, 0xd4, 0x14, 0xc0, 0x38, 0x21, 0xbc, 0x58, 0x20, 0x63,
344 },
345};
346
347static const struct {
348 uint8_t seed[20];
349 uint8_t p[30];
350 uint8_t a[30];
351 uint8_t b[30];
352 uint8_t x[30];
353 uint8_t y[30];
354 uint8_t order[30];
355} _EC_X9_62_PRIME_239V3 = {
356 .seed = {
357 0x7d, 0x73, 0x74, 0x16, 0x8f, 0xfe, 0x34, 0x71, 0xb6, 0x0a,
358 0x85, 0x76, 0x86, 0xa1, 0x94, 0x75, 0xd3, 0xbf, 0xa2, 0xff,
359 },
360 .p = {
361 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
362 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
363 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
364 },
365 .a = {
366 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
367 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
368 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfc,
369 },
370 .b = {
371 0x25, 0x57, 0x05, 0xfa, 0x2a, 0x30, 0x66, 0x54, 0xb1, 0xf4,
372 0xcb, 0x03, 0xd6, 0xa7, 0x50, 0xa3, 0x0c, 0x25, 0x01, 0x02,
373 0xd4, 0x98, 0x87, 0x17, 0xd9, 0xba, 0x15, 0xab, 0x6d, 0x3e,
374 },
375 .x = {
376 0x67, 0x68, 0xae, 0x8e, 0x18, 0xbb, 0x92, 0xcf, 0xcf, 0x00,
377 0x5c, 0x94, 0x9a, 0xa2, 0xc6, 0xd9, 0x48, 0x53, 0xd0, 0xe6,
378 0x60, 0xbb, 0xf8, 0x54, 0xb1, 0xc9, 0x50, 0x5f, 0xe9, 0x5a,
379 },
380 .y = {
381 0x16, 0x07, 0xe6, 0x89, 0x8f, 0x39, 0x0c, 0x06, 0xbc, 0x1d,
382 0x55, 0x2b, 0xad, 0x22, 0x6f, 0x3b, 0x6f, 0xcf, 0xe4, 0x8b,
383 0x6e, 0x81, 0x84, 0x99, 0xaf, 0x18, 0xe3, 0xed, 0x6c, 0xf3,
384 },
385 .order = {
386 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
387 0xff, 0xff, 0x7f, 0xff, 0xff, 0x97, 0x5d, 0xeb, 0x41, 0xb3,
388 0xa6, 0x05, 0x7c, 0x3c, 0x43, 0x21, 0x46, 0x52, 0x65, 0x51,
389 },
390};
391
392static const struct {
393 uint8_t seed[20];
394 uint8_t p[32];
395 uint8_t a[32];
396 uint8_t b[32];
397 uint8_t x[32];
398 uint8_t y[32];
399 uint8_t order[32];
400} _EC_X9_62_PRIME_256V1 = {
401 .seed = {
402 0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66,
403 0x78, 0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90,
404 },
405 .p = {
406 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
407 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
408 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
409 0xff, 0xff,
410 },
411 .a = {
412 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
413 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
414 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
415 0xff, 0xfc,
416 },
417 .b = {
418 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb,
419 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0,
420 0xcc, 0x53, 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2,
421 0x60, 0x4b,
422 },
423 .x = {
424 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc,
425 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81,
426 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98,
427 0xc2, 0x96,
428 },
429 .y = {
430 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7,
431 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57,
432 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf,
433 0x51, 0xf5,
434 },
435 .order = {
436 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
437 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad,
438 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63,
439 0x25, 0x51,
440 },
441};
442
443static const struct {
444 uint8_t p[29]; 306 uint8_t p[29];
445 uint8_t a[29]; 307 uint8_t a[29];
446 uint8_t b[29]; 308 uint8_t b[29];
@@ -1121,7 +983,21 @@ static const struct ec_curve {
1121 .order = _EC_SECG_PRIME_256K1.order, 983 .order = _EC_SECG_PRIME_256K1.order,
1122 .cofactor = 1, 984 .cofactor = 1,
1123 }, 985 },
1124 /* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */ 986 {
987 /* Everyone except OpenSSL calls this secp256r1 or P-256. */
988 .comment = "X9.62/SECG curve prime256v1",
989 .nid = NID_X9_62_prime256v1,
990 .seed_len = sizeof(_EC_NIST_PRIME_256.seed),
991 .param_len = sizeof(_EC_NIST_PRIME_256.p),
992 .seed = _EC_NIST_PRIME_256.seed,
993 .p = _EC_NIST_PRIME_256.p,
994 .a = _EC_NIST_PRIME_256.a,
995 .b = _EC_NIST_PRIME_256.b,
996 .x = _EC_NIST_PRIME_256.x,
997 .y = _EC_NIST_PRIME_256.y,
998 .order = _EC_NIST_PRIME_256.order,
999 .cofactor = 1,
1000 },
1125 { 1001 {
1126 .comment = "NIST/SECG curve secp384r1", 1002 .comment = "NIST/SECG curve secp384r1",
1127 .nid = NID_secp384r1, 1003 .nid = NID_secp384r1,
@@ -1150,63 +1026,6 @@ static const struct ec_curve {
1150 .order = _EC_NIST_PRIME_521.order, 1026 .order = _EC_NIST_PRIME_521.order,
1151 .cofactor = 1, 1027 .cofactor = 1,
1152 }, 1028 },
1153 /* X9.62 curves */
1154 {
1155 .comment = "X9.62 curve prime239v1",
1156 .nid = NID_X9_62_prime239v1,
1157 .seed_len = sizeof(_EC_X9_62_PRIME_239V1.seed),
1158 .param_len = sizeof(_EC_X9_62_PRIME_239V1.p),
1159 .seed = _EC_X9_62_PRIME_239V1.seed,
1160 .p = _EC_X9_62_PRIME_239V1.p,
1161 .a = _EC_X9_62_PRIME_239V1.a,
1162 .b = _EC_X9_62_PRIME_239V1.b,
1163 .x = _EC_X9_62_PRIME_239V1.x,
1164 .y = _EC_X9_62_PRIME_239V1.y,
1165 .order = _EC_X9_62_PRIME_239V1.order,
1166 .cofactor = 1,
1167 },
1168 {
1169 .comment = "X9.62 curve prime239v2",
1170 .nid = NID_X9_62_prime239v2,
1171 .seed_len = sizeof(_EC_X9_62_PRIME_239V2.seed),
1172 .param_len = sizeof(_EC_X9_62_PRIME_239V2.p),
1173 .seed = _EC_X9_62_PRIME_239V2.seed,
1174 .p = _EC_X9_62_PRIME_239V2.p,
1175 .a = _EC_X9_62_PRIME_239V2.a,
1176 .b = _EC_X9_62_PRIME_239V2.b,
1177 .x = _EC_X9_62_PRIME_239V2.x,
1178 .y = _EC_X9_62_PRIME_239V2.y,
1179 .order = _EC_X9_62_PRIME_239V2.order,
1180 .cofactor = 1,
1181 },
1182 {
1183 .comment = "X9.62 curve prime239v3",
1184 .nid = NID_X9_62_prime239v3,
1185 .seed_len = sizeof(_EC_X9_62_PRIME_239V3.seed),
1186 .param_len = sizeof(_EC_X9_62_PRIME_239V3.p),
1187 .seed = _EC_X9_62_PRIME_239V3.seed,
1188 .p = _EC_X9_62_PRIME_239V3.p,
1189 .a = _EC_X9_62_PRIME_239V3.a,
1190 .b = _EC_X9_62_PRIME_239V3.b,
1191 .x = _EC_X9_62_PRIME_239V3.x,
1192 .y = _EC_X9_62_PRIME_239V3.y,
1193 .order = _EC_X9_62_PRIME_239V3.order,
1194 .cofactor = 1,
1195 },
1196 {
1197 .comment = "X9.62/SECG curve prime256v1",
1198 .nid = NID_X9_62_prime256v1,
1199 .seed_len = sizeof(_EC_X9_62_PRIME_256V1.seed),
1200 .param_len = sizeof(_EC_X9_62_PRIME_256V1.p),
1201 .seed = _EC_X9_62_PRIME_256V1.seed,
1202 .p = _EC_X9_62_PRIME_256V1.p,
1203 .a = _EC_X9_62_PRIME_256V1.a,
1204 .b = _EC_X9_62_PRIME_256V1.b,
1205 .x = _EC_X9_62_PRIME_256V1.x,
1206 .y = _EC_X9_62_PRIME_256V1.y,
1207 .order = _EC_X9_62_PRIME_256V1.order,
1208 .cofactor = 1,
1209 },
1210 /* RFC 5639 curves */ 1029 /* RFC 5639 curves */
1211 { 1030 {
1212 .comment = "RFC 5639 curve brainpoolP224r1", 1031 .comment = "RFC 5639 curve brainpoolP224r1",
@@ -1221,7 +1040,7 @@ static const struct ec_curve {
1221 .cofactor = 1, 1040 .cofactor = 1,
1222 }, 1041 },
1223 { 1042 {
1224 .comment = "RFC 5639 curve brainpoolP224r2", 1043 .comment = "RFC 5639 curve brainpoolP224t1",
1225 .nid = NID_brainpoolP224t1, 1044 .nid = NID_brainpoolP224t1,
1226 .param_len = sizeof(_EC_brainpoolP224t1.p), 1045 .param_len = sizeof(_EC_brainpoolP224t1.p),
1227 .p = _EC_brainpoolP224t1.p, 1046 .p = _EC_brainpoolP224t1.p,
@@ -1573,7 +1392,7 @@ ec_curve_from_group(const EC_GROUP *group)
1573 if ((cofactor = EC_GROUP_get0_cofactor(group)) != NULL) { 1392 if ((cofactor = EC_GROUP_get0_cofactor(group)) != NULL) {
1574 BN_ULONG cofactor_word; 1393 BN_ULONG cofactor_word;
1575 1394
1576 if ((cofactor_word = BN_get_word(cofactor)) == BN_MASK2) 1395 if ((cofactor_word = BN_get_word(cofactor)) == (BN_ULONG)-1)
1577 goto err; 1396 goto err;
1578 if (cofactor_word > INT_MAX) 1397 if (cofactor_word > INT_MAX)
1579 goto err; 1398 goto err;
diff --git a/src/lib/libcrypto/ec/ec_field.c b/src/lib/libcrypto/ec/ec_field.c
new file mode 100644
index 0000000000..6576526e77
--- /dev/null
+++ b/src/lib/libcrypto/ec/ec_field.c
@@ -0,0 +1,202 @@
1/* $OpenBSD: ec_field.c,v 1.3 2025/08/02 16:20:00 jsing Exp $ */
2/*
3 * Copyright (c) 2024 Joel Sing <jsing@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <string.h>
19
20#include <openssl/ec.h>
21
22#include "bn_local.h"
23#include "bn_internal.h"
24#include "ec_local.h"
25#include "ec_internal.h"
26
27int
28ec_field_modulus_from_bn(EC_FIELD_MODULUS *fm, const BIGNUM *bn, BN_CTX *ctx)
29{
30 BN_MONT_CTX *mctx = NULL;
31 size_t i;
32 int ret = 0;
33
34 if (BN_is_negative(bn))
35 goto err;
36 if (BN_num_bits(bn) > EC_FIELD_ELEMENT_MAX_BITS)
37 goto err;
38
39 memset(fm, 0, sizeof(*fm));
40
41 fm->n = (BN_num_bits(bn) + BN_BITS2 - 1) / BN_BITS2;
42
43 for (i = 0; i < bn->top; i++)
44 fm->m.w[i] = bn->d[i];
45
46 /* XXX - implement this without BN_MONT_CTX. */
47 if ((mctx = BN_MONT_CTX_new()) == NULL)
48 goto err;
49 if (!BN_MONT_CTX_set(mctx, bn, ctx))
50 goto err;
51
52 for (i = 0; i < mctx->RR.top; i++)
53 fm->rr.w[i] = mctx->RR.d[i];
54
55 fm->minv0 = mctx->n0[0];
56
57 ret = 1;
58
59 err:
60 BN_MONT_CTX_free(mctx);
61
62 return ret;
63}
64
65int
66ec_field_element_from_bn(const EC_FIELD_MODULUS *fm, const EC_GROUP *group,
67 EC_FIELD_ELEMENT *fe, const BIGNUM *bn, BN_CTX *ctx)
68{
69 BN_ULONG t[EC_FIELD_ELEMENT_MAX_WORDS * 2 + 2];
70 BIGNUM *tmp;
71 size_t i;
72 int ret = 0;
73
74 BN_CTX_start(ctx);
75
76 if ((tmp = BN_CTX_get(ctx)) == NULL)
77 goto err;
78
79 /* XXX - enforce 0 <= n < p. */
80
81 if (BN_num_bits(bn) > EC_FIELD_ELEMENT_MAX_BITS)
82 goto err;
83
84 /* XXX - do this without BN. */
85 if (!BN_nnmod(tmp, bn, group->p, ctx))
86 goto err;
87
88 if (BN_num_bits(tmp) > EC_FIELD_ELEMENT_MAX_BITS)
89 abort();
90
91 memset(fe->w, 0, sizeof(fe->w));
92
93 for (i = 0; i < tmp->top; i++)
94 fe->w[i] = tmp->d[i];
95
96 bn_mod_mul_words(fe->w, fe->w, fm->rr.w, fm->m.w, t, fm->minv0, fm->n);
97
98 ret = 1;
99
100 err:
101 BN_CTX_end(ctx);
102
103 return ret;
104}
105
106int
107ec_field_element_to_bn(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *fe,
108 BIGNUM *bn, BN_CTX *ctx)
109{
110 BN_ULONG t[EC_FIELD_ELEMENT_MAX_WORDS * 2 + 2];
111 size_t i;
112
113 if (!bn_wexpand(bn, fm->n))
114 return 0;
115
116 memset(t, 0, sizeof(t));
117 for (i = 0; i < fm->n; i++)
118 t[i] = fe->w[i];
119
120 bn_montgomery_reduce_words(bn->d, t, fm->m.w, fm->minv0, fm->n);
121
122 bn->top = fm->n;
123 bn_correct_top(bn);
124
125 return 1;
126}
127
128void
129ec_field_element_copy(EC_FIELD_ELEMENT *dst, const EC_FIELD_ELEMENT *src)
130{
131 memcpy(dst, src, sizeof(EC_FIELD_ELEMENT));
132}
133
134void
135ec_field_element_select(const EC_FIELD_MODULUS *fm, EC_FIELD_ELEMENT *r,
136 const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b, int conditional)
137{
138 BN_ULONG mask;
139 int i;
140
141 mask = bn_ct_eq_zero_mask(conditional);
142
143 for (i = 0; i < fm->n; i++)
144 r->w[i] = (a->w[i] & mask) | (b->w[i] & ~mask);
145}
146
147int
148ec_field_element_equal(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *a,
149 const EC_FIELD_ELEMENT *b)
150{
151 BN_ULONG v = 0;
152 int i;
153
154 for (i = 0; i < fm->n; i++)
155 v |= a->w[i] ^ b->w[i];
156
157 return bn_ct_eq_zero(v);
158}
159
160int
161ec_field_element_is_zero(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *fe)
162{
163 BN_ULONG v = 0;
164 int i;
165
166 for (i = 0; i < fm->n; i++)
167 v |= fe->w[i];
168
169 return bn_ct_eq_zero(v);
170}
171
172void
173ec_field_element_add(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r,
174 const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b)
175{
176 bn_mod_add_words(r->w, a->w, b->w, m->m.w, m->n);
177}
178
179void
180ec_field_element_sub(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r,
181 const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b)
182{
183 bn_mod_sub_words(r->w, a->w, b->w, m->m.w, m->n);
184}
185
186void
187ec_field_element_mul(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r,
188 const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b)
189{
190 BN_ULONG t[EC_FIELD_ELEMENT_MAX_WORDS * 2 + 2];
191
192 bn_mod_mul_words(r->w, a->w, b->w, m->m.w, t, m->minv0, m->n);
193}
194
195void
196ec_field_element_sqr(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r,
197 const EC_FIELD_ELEMENT *a)
198{
199 BN_ULONG t[EC_FIELD_ELEMENT_MAX_WORDS * 2 + 2];
200
201 bn_mod_sqr_words(r->w, a->w, m->m.w, t, m->minv0, m->n);
202}
diff --git a/src/lib/libcrypto/ec/ec_internal.h b/src/lib/libcrypto/ec/ec_internal.h
new file mode 100644
index 0000000000..de0affa206
--- /dev/null
+++ b/src/lib/libcrypto/ec/ec_internal.h
@@ -0,0 +1,65 @@
1/* $OpenBSD: ec_internal.h,v 1.3 2025/12/05 14:12:32 tb Exp $ */
2/*
3 * Copyright (c) 2024 Joel Sing <jsing@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <openssl/bn.h>
19
20#ifndef HEADER_EC_INTERNAL_H
21#define HEADER_EC_INTERNAL_H
22
23#define EC_FIELD_ELEMENT_MAX_BITS 521
24#define EC_FIELD_ELEMENT_MAX_BYTES \
25 (EC_FIELD_ELEMENT_MAX_BITS + 7) / 8
26#define EC_FIELD_ELEMENT_MAX_WORDS \
27 ((EC_FIELD_ELEMENT_MAX_BYTES + sizeof(BN_ULONG) - 1) / sizeof(BN_ULONG))
28
29typedef struct {
30 BN_ULONG w[EC_FIELD_ELEMENT_MAX_WORDS];
31} EC_FIELD_ELEMENT;
32
33typedef struct {
34 size_t n;
35 EC_FIELD_ELEMENT m;
36 EC_FIELD_ELEMENT rr;
37 BN_ULONG minv0;
38} EC_FIELD_MODULUS;
39
40int ec_field_modulus_from_bn(EC_FIELD_MODULUS *fm, const BIGNUM *bn,
41 BN_CTX *ctx);
42
43int ec_field_element_from_bn(const EC_FIELD_MODULUS *fm, const EC_GROUP *group,
44 EC_FIELD_ELEMENT *fe, const BIGNUM *bn, BN_CTX *ctx);
45int ec_field_element_to_bn(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *fe,
46 BIGNUM *bn, BN_CTX *ctx);
47
48void ec_field_element_copy(EC_FIELD_ELEMENT *dst, const EC_FIELD_ELEMENT *src);
49void ec_field_element_select(const EC_FIELD_MODULUS *fm, EC_FIELD_ELEMENT *r,
50 const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b, int conditional);
51
52int ec_field_element_equal(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *a,
53 const EC_FIELD_ELEMENT *b);
54int ec_field_element_is_zero(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *fe);
55
56void ec_field_element_add(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r,
57 const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b);
58void ec_field_element_sub(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r,
59 const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b);
60void ec_field_element_mul(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r,
61 const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b);
62void ec_field_element_sqr(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r,
63 const EC_FIELD_ELEMENT *a);
64
65#endif
diff --git a/src/lib/libcrypto/ec/ec_key.c b/src/lib/libcrypto/ec/ec_key.c
index 6257d67cd1..e9777019c8 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.51 2025/01/25 10:34:36 tb Exp $ */ 1/* $OpenBSD: ec_key.c,v 1.52 2025/05/10 05:54:38 tb Exp $ */
2/* 2/*
3 * Written by Nils Larsch for the OpenSSL project. 3 * Written by Nils Larsch for the OpenSSL project.
4 */ 4 */
@@ -66,11 +66,11 @@
66#include <openssl/opensslconf.h> 66#include <openssl/opensslconf.h>
67 67
68#include <openssl/ec.h> 68#include <openssl/ec.h>
69#include <openssl/err.h>
70 69
71#include "bn_local.h" 70#include "bn_local.h"
72#include "ec_local.h" 71#include "ec_local.h"
73#include "ecdsa_local.h" 72#include "ecdsa_local.h"
73#include "err_local.h"
74 74
75EC_KEY * 75EC_KEY *
76EC_KEY_new(void) 76EC_KEY_new(void)
diff --git a/src/lib/libcrypto/ec/ec_lib.c b/src/lib/libcrypto/ec/ec_lib.c
index 7982d23f06..30b2cf95b8 100644
--- a/src/lib/libcrypto/ec/ec_lib.c
+++ b/src/lib/libcrypto/ec/ec_lib.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec_lib.c,v 1.123 2025/03/24 13:07:04 jsing Exp $ */ 1/* $OpenBSD: ec_lib.c,v 1.131 2025/12/26 18:49:13 tb Exp $ */
2/* 2/*
3 * Originally written by Bodo Moeller for the OpenSSL project. 3 * Originally written by Bodo Moeller for the OpenSSL project.
4 */ 4 */
@@ -68,12 +68,12 @@
68 68
69#include <openssl/bn.h> 69#include <openssl/bn.h>
70#include <openssl/ec.h> 70#include <openssl/ec.h>
71#include <openssl/err.h>
72#include <openssl/objects.h> 71#include <openssl/objects.h>
73#include <openssl/opensslv.h> 72#include <openssl/opensslv.h>
74 73
75#include "bn_local.h" 74#include "bn_local.h"
76#include "ec_local.h" 75#include "ec_local.h"
76#include "err_local.h"
77 77
78EC_GROUP * 78EC_GROUP *
79EC_GROUP_new(const EC_METHOD *meth) 79EC_GROUP_new(const EC_METHOD *meth)
@@ -165,6 +165,10 @@ EC_GROUP_copy(EC_GROUP *dst, const EC_GROUP *src)
165 165
166 dst->a_is_minus3 = src->a_is_minus3; 166 dst->a_is_minus3 = src->a_is_minus3;
167 167
168 memcpy(&dst->fm, &src->fm, sizeof(src->fm));
169 memcpy(&dst->fe_a, &src->fe_a, sizeof(src->fe_a));
170 memcpy(&dst->fe_b, &src->fe_b, sizeof(src->fe_b));
171
168 BN_MONT_CTX_free(dst->mont_ctx); 172 BN_MONT_CTX_free(dst->mont_ctx);
169 dst->mont_ctx = NULL; 173 dst->mont_ctx = NULL;
170 if (src->mont_ctx != NULL) { 174 if (src->mont_ctx != NULL) {
@@ -788,6 +792,16 @@ EC_GROUP_cmp(const EC_GROUP *group1, const EC_GROUP *group2, BN_CTX *ctx_in)
788} 792}
789LCRYPTO_ALIAS(EC_GROUP_cmp); 793LCRYPTO_ALIAS(EC_GROUP_cmp);
790 794
795int
796ec_group_and_point_compatible(const EC_GROUP *group, const EC_POINT *point)
797{
798 if (group->meth != point->meth)
799 return 0;
800 if (group->nid == NID_undef || point->nid == NID_undef)
801 return 1;
802 return group->nid == point->nid;
803}
804
791EC_POINT * 805EC_POINT *
792EC_POINT_new(const EC_GROUP *group) 806EC_POINT_new(const EC_GROUP *group)
793{ 807{
@@ -811,6 +825,7 @@ EC_POINT_new(const EC_GROUP *group)
811 goto err; 825 goto err;
812 826
813 point->meth = group->meth; 827 point->meth = group->meth;
828 point->nid = group->nid;
814 829
815 return point; 830 return point;
816 831
@@ -852,6 +867,8 @@ EC_POINT_copy(EC_POINT *dst, const EC_POINT *src)
852 if (dst == src) 867 if (dst == src)
853 return 1; 868 return 1;
854 869
870 dst->nid = src->nid;
871
855 if (!bn_copy(dst->X, src->X)) 872 if (!bn_copy(dst->X, src->X))
856 return 0; 873 return 0;
857 if (!bn_copy(dst->Y, src->Y)) 874 if (!bn_copy(dst->Y, src->Y))
@@ -860,6 +877,10 @@ EC_POINT_copy(EC_POINT *dst, const EC_POINT *src)
860 return 0; 877 return 0;
861 dst->Z_is_one = src->Z_is_one; 878 dst->Z_is_one = src->Z_is_one;
862 879
880 memcpy(&dst->fe_x, &src->fe_x, sizeof(dst->fe_x));
881 memcpy(&dst->fe_y, &src->fe_y, sizeof(dst->fe_y));
882 memcpy(&dst->fe_z, &src->fe_z, sizeof(dst->fe_z));
883
863 return 1; 884 return 1;
864} 885}
865LCRYPTO_ALIAS(EC_POINT_copy); 886LCRYPTO_ALIAS(EC_POINT_copy);
@@ -890,15 +911,11 @@ LCRYPTO_ALIAS(EC_POINT_dup);
890int 911int
891EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) 912EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
892{ 913{
893 if (group->meth != point->meth) { 914 if (!ec_group_and_point_compatible(group, point)) {
894 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 915 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
895 return 0; 916 return 0;
896 } 917 }
897 918 return group->meth->point_set_to_infinity(group, point);
898 BN_zero(point->Z);
899 point->Z_is_one = 0;
900
901 return 1;
902} 919}
903LCRYPTO_ALIAS(EC_POINT_set_to_infinity); 920LCRYPTO_ALIAS(EC_POINT_set_to_infinity);
904 921
@@ -918,7 +935,7 @@ EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
918 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 935 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
919 goto err; 936 goto err;
920 } 937 }
921 if (group->meth != point->meth) { 938 if (!ec_group_and_point_compatible(group, point)) {
922 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 939 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
923 goto err; 940 goto err;
924 } 941 }
@@ -969,7 +986,7 @@ EC_POINT_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
969 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 986 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
970 goto err; 987 goto err;
971 } 988 }
972 if (group->meth != point->meth) { 989 if (!ec_group_and_point_compatible(group, point)) {
973 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 990 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
974 goto err; 991 goto err;
975 } 992 }
@@ -1119,8 +1136,9 @@ EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
1119 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1136 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1120 goto err; 1137 goto err;
1121 } 1138 }
1122 if (group->meth != r->meth || group->meth != a->meth || 1139 if (!ec_group_and_point_compatible(group, r) ||
1123 group->meth != b->meth) { 1140 !ec_group_and_point_compatible(group, a) ||
1141 !ec_group_and_point_compatible(group, b)) {
1124 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 1142 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
1125 goto err; 1143 goto err;
1126 } 1144 }
@@ -1150,7 +1168,8 @@ EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
1150 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1168 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1151 goto err; 1169 goto err;
1152 } 1170 }
1153 if (group->meth != r->meth || r->meth != a->meth) { 1171 if (!ec_group_and_point_compatible(group, r) ||
1172 !ec_group_and_point_compatible(group, a)) {
1154 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 1173 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
1155 goto err; 1174 goto err;
1156 } 1175 }
@@ -1179,7 +1198,7 @@ EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx_in)
1179 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1198 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1180 goto err; 1199 goto err;
1181 } 1200 }
1182 if (group->meth != a->meth) { 1201 if (!ec_group_and_point_compatible(group, a)) {
1183 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 1202 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
1184 goto err; 1203 goto err;
1185 } 1204 }
@@ -1196,12 +1215,11 @@ LCRYPTO_ALIAS(EC_POINT_invert);
1196int 1215int
1197EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) 1216EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
1198{ 1217{
1199 if (group->meth != point->meth) { 1218 if (!ec_group_and_point_compatible(group, point)) {
1200 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 1219 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
1201 return 0; 1220 return 0;
1202 } 1221 }
1203 1222 return group->meth->point_is_at_infinity(group, point);
1204 return BN_is_zero(point->Z);
1205} 1223}
1206LCRYPTO_ALIAS(EC_POINT_is_at_infinity); 1224LCRYPTO_ALIAS(EC_POINT_is_at_infinity);
1207 1225
@@ -1221,7 +1239,7 @@ EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
1221 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1239 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1222 goto err; 1240 goto err;
1223 } 1241 }
1224 if (group->meth != point->meth) { 1242 if (!ec_group_and_point_compatible(group, point)) {
1225 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 1243 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
1226 goto err; 1244 goto err;
1227 } 1245 }
@@ -1251,7 +1269,8 @@ EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
1251 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1269 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1252 goto err; 1270 goto err;
1253 } 1271 }
1254 if (group->meth != a->meth || a->meth != b->meth) { 1272 if (!ec_group_and_point_compatible(group, a) ||
1273 !ec_group_and_point_compatible(group, b)) {
1255 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 1274 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
1256 goto err; 1275 goto err;
1257 } 1276 }
@@ -1324,6 +1343,12 @@ EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
1324 goto err; 1343 goto err;
1325 } 1344 }
1326 1345
1346 if (!ec_group_and_point_compatible(group, r) ||
1347 (point != NULL && !ec_group_and_point_compatible(group, point))) {
1348 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
1349 goto err;
1350 }
1351
1327 if (g_scalar != NULL && point == NULL && p_scalar == NULL) { 1352 if (g_scalar != NULL && point == NULL && p_scalar == NULL) {
1328 /* 1353 /*
1329 * In this case we want to compute g_scalar * GeneratorPoint: 1354 * In this case we want to compute g_scalar * GeneratorPoint:
diff --git a/src/lib/libcrypto/ec/ec_local.h b/src/lib/libcrypto/ec/ec_local.h
index c7a54d3a2b..d84e92767c 100644
--- a/src/lib/libcrypto/ec/ec_local.h
+++ b/src/lib/libcrypto/ec/ec_local.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec_local.h,v 1.67 2025/03/24 13:07:04 jsing Exp $ */ 1/* $OpenBSD: ec_local.h,v 1.73 2025/12/26 18:42:33 tb Exp $ */
2/* 2/*
3 * Originally written by Bodo Moeller for the OpenSSL project. 3 * Originally written by Bodo Moeller for the OpenSSL project.
4 */ 4 */
@@ -69,6 +69,9 @@
69 * 69 *
70 */ 70 */
71 71
72#ifndef HEADER_EC_LOCAL_H
73#define HEADER_EC_LOCAL_H
74
72#include <stdlib.h> 75#include <stdlib.h>
73 76
74#include <openssl/bn.h> 77#include <openssl/bn.h>
@@ -76,6 +79,7 @@
76#include <openssl/objects.h> 79#include <openssl/objects.h>
77 80
78#include "bn_local.h" 81#include "bn_local.h"
82#include "ec_internal.h"
79 83
80__BEGIN_HIDDEN_DECLS 84__BEGIN_HIDDEN_DECLS
81 85
@@ -85,6 +89,9 @@ typedef struct ec_method_st {
85 int (*group_get_curve)(const EC_GROUP *, BIGNUM *p, BIGNUM *a, 89 int (*group_get_curve)(const EC_GROUP *, BIGNUM *p, BIGNUM *a,
86 BIGNUM *b, BN_CTX *); 90 BIGNUM *b, BN_CTX *);
87 91
92 int (*point_set_to_infinity)(const EC_GROUP *, EC_POINT *);
93 int (*point_is_at_infinity)(const EC_GROUP *, const EC_POINT *);
94
88 int (*point_is_on_curve)(const EC_GROUP *, const EC_POINT *, BN_CTX *); 95 int (*point_is_on_curve)(const EC_GROUP *, const EC_POINT *, BN_CTX *);
89 int (*point_cmp)(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, 96 int (*point_cmp)(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b,
90 BN_CTX *); 97 BN_CTX *);
@@ -155,10 +162,15 @@ struct ec_group_st {
155 162
156 /* Montgomery context used by EC_GFp_mont_method. */ 163 /* Montgomery context used by EC_GFp_mont_method. */
157 BN_MONT_CTX *mont_ctx; 164 BN_MONT_CTX *mont_ctx;
165
166 EC_FIELD_MODULUS fm;
167 EC_FIELD_ELEMENT fe_a;
168 EC_FIELD_ELEMENT fe_b;
158} /* EC_GROUP */; 169} /* EC_GROUP */;
159 170
160struct ec_point_st { 171struct ec_point_st {
161 const EC_METHOD *meth; 172 const EC_METHOD *meth;
173 int nid;
162 174
163 /* 175 /*
164 * Jacobian projective coordinates: (X, Y, Z) represents (X/Z^2, Y/Z^3) 176 * Jacobian projective coordinates: (X, Y, Z) represents (X/Z^2, Y/Z^3)
@@ -168,10 +180,15 @@ struct ec_point_st {
168 BIGNUM *Y; 180 BIGNUM *Y;
169 BIGNUM *Z; 181 BIGNUM *Z;
170 int Z_is_one; /* enable optimized point arithmetics for special case */ 182 int Z_is_one; /* enable optimized point arithmetics for special case */
183
184 EC_FIELD_ELEMENT fe_x;
185 EC_FIELD_ELEMENT fe_y;
186 EC_FIELD_ELEMENT fe_z;
171} /* EC_POINT */; 187} /* EC_POINT */;
172 188
173const EC_METHOD *EC_GFp_simple_method(void); 189const EC_METHOD *EC_GFp_simple_method(void);
174const EC_METHOD *EC_GFp_mont_method(void); 190const EC_METHOD *EC_GFp_mont_method(void);
191const EC_METHOD *EC_GFp_homogeneous_projective_method(void);
175 192
176/* Compute r = scalar1 * point1 + scalar2 * point2 in non-constant time. */ 193/* Compute r = scalar1 * point1 + scalar2 * point2 in non-constant time. */
177int ec_wnaf_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar1, 194int ec_wnaf_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar1,
@@ -179,6 +196,7 @@ int ec_wnaf_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar1,
179 BN_CTX *ctx); 196 BN_CTX *ctx);
180 197
181int ec_group_is_builtin_curve(const EC_GROUP *group, int *out_nid); 198int ec_group_is_builtin_curve(const EC_GROUP *group, int *out_nid);
199int ec_group_and_point_compatible(const EC_GROUP *group, const EC_POINT *point);
182 200
183/* 201/*
184 * Wrappers around the unergonomic EC_POINT_{oct2point,point2oct}(). 202 * Wrappers around the unergonomic EC_POINT_{oct2point,point2oct}().
@@ -252,3 +270,5 @@ int ecdh_KDF_X9_63(unsigned char *out, size_t outlen, const unsigned char *Z,
252 size_t Zlen, const unsigned char *sinfo, size_t sinfolen, const EVP_MD *md); 270 size_t Zlen, const unsigned char *sinfo, size_t sinfolen, const EVP_MD *md);
253 271
254__END_HIDDEN_DECLS 272__END_HIDDEN_DECLS
273
274#endif /* HEADER_EC_LOCAL_H */
diff --git a/src/lib/libcrypto/ec/ec_mult.c b/src/lib/libcrypto/ec/ec_mult.c
index 673696a9fd..067df9a2a2 100644
--- a/src/lib/libcrypto/ec/ec_mult.c
+++ b/src/lib/libcrypto/ec/ec_mult.c
@@ -1,64 +1,19 @@
1/* $OpenBSD: ec_mult.c,v 1.58 2025/03/24 13:07:04 jsing Exp $ */ 1/* $OpenBSD: ec_mult.c,v 1.61 2025/12/26 18:44:19 tb Exp $ */
2
2/* 3/*
3 * Originally written by Bodo Moeller and Nils Larsch for the OpenSSL project. 4 * Copyright (c) 2024 Theo Buehler <tb@openbsd.org>
4 */
5/* ====================================================================
6 * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24 * 5 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 6 * Permission to use, copy, modify, and distribute this software for any
26 * endorse or promote products derived from this software without 7 * purpose with or without fee is hereby granted, provided that the above
27 * prior written permission. For written permission, please contact 8 * copyright notice and this permission notice appear in all copies.
28 * openssl-core@openssl.org.
29 * 9 *
30 * 5. Products derived from this software may not be called "OpenSSL" 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
31 * nor may "OpenSSL" appear in their names without prior written 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
32 * permission of the OpenSSL Project. 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
33 * 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
34 * 6. Redistributions of any form whatsoever must retain the following 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
35 * acknowledgment: 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
36 * "This product includes software developed by the OpenSSL Project 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
37 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58/* ====================================================================
59 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60 * Portions of this software developed by SUN MICROSYSTEMS, INC.,
61 * and contributed to the OpenSSL project.
62 */ 17 */
63 18
64#include <stdint.h> 19#include <stdint.h>
@@ -67,9 +22,9 @@
67 22
68#include <openssl/bn.h> 23#include <openssl/bn.h>
69#include <openssl/ec.h> 24#include <openssl/ec.h>
70#include <openssl/err.h>
71 25
72#include "ec_local.h" 26#include "ec_local.h"
27#include "err_local.h"
73 28
74/* Holds the wNAF digits of bn and the corresponding odd multiples of point. */ 29/* Holds the wNAF digits of bn and the corresponding odd multiples of point. */
75struct ec_wnaf { 30struct ec_wnaf {
@@ -332,8 +287,9 @@ ec_wnaf_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar1,
332 ECerror(ERR_R_PASSED_NULL_PARAMETER); 287 ECerror(ERR_R_PASSED_NULL_PARAMETER);
333 goto err; 288 goto err;
334 } 289 }
335 if (group->meth != r->meth || group->meth != point1->meth || 290 if (!ec_group_and_point_compatible(group, r) ||
336 group->meth != point2->meth) { 291 !ec_group_and_point_compatible(group, point1) ||
292 !ec_group_and_point_compatible(group, point2)) {
337 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 293 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
338 goto err; 294 goto err;
339 } 295 }
diff --git a/src/lib/libcrypto/ec/ec_pmeth.c b/src/lib/libcrypto/ec/ec_pmeth.c
index 85ac4822d1..69bf7e741a 100644
--- a/src/lib/libcrypto/ec/ec_pmeth.c
+++ b/src/lib/libcrypto/ec/ec_pmeth.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec_pmeth.c,v 1.26 2025/03/13 10:39:51 tb Exp $ */ 1/* $OpenBSD: ec_pmeth.c,v 1.27 2025/05/10 05:54:38 tb Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2006. 3 * project 2006.
4 */ 4 */
@@ -62,12 +62,12 @@
62 62
63#include <openssl/asn1t.h> 63#include <openssl/asn1t.h>
64#include <openssl/ec.h> 64#include <openssl/ec.h>
65#include <openssl/err.h>
66#include <openssl/evp.h> 65#include <openssl/evp.h>
67#include <openssl/x509.h> 66#include <openssl/x509.h>
68 67
69#include "bn_local.h" 68#include "bn_local.h"
70#include "ec_local.h" 69#include "ec_local.h"
70#include "err_local.h"
71#include "evp_local.h" 71#include "evp_local.h"
72 72
73/* EC pkey context structure */ 73/* EC pkey context structure */
diff --git a/src/lib/libcrypto/ec/eck_prn.c b/src/lib/libcrypto/ec/eck_prn.c
index c40a64966a..ed5fdce9c1 100644
--- a/src/lib/libcrypto/ec/eck_prn.c
+++ b/src/lib/libcrypto/ec/eck_prn.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: eck_prn.c,v 1.41 2025/01/25 10:30:17 tb Exp $ */ 1/* $OpenBSD: eck_prn.c,v 1.42 2025/05/10 05:54:38 tb Exp $ */
2/* 2/*
3 * Written by Nils Larsch for the OpenSSL project. 3 * Written by Nils Larsch for the OpenSSL project.
4 */ 4 */
@@ -66,12 +66,12 @@
66#include <openssl/bio.h> 66#include <openssl/bio.h>
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/evp.h> 69#include <openssl/evp.h>
71#include <openssl/objects.h> 70#include <openssl/objects.h>
72 71
73#include "bn_local.h" 72#include "bn_local.h"
74#include "ec_local.h" 73#include "ec_local.h"
74#include "err_local.h"
75 75
76int 76int
77EC_KEY_print(BIO *bio, const EC_KEY *ec_key, int off) 77EC_KEY_print(BIO *bio, const EC_KEY *ec_key, int off)
diff --git a/src/lib/libcrypto/ec/ecp_hp_methods.c b/src/lib/libcrypto/ec/ecp_hp_methods.c
new file mode 100644
index 0000000000..0b34a55b9d
--- /dev/null
+++ b/src/lib/libcrypto/ec/ecp_hp_methods.c
@@ -0,0 +1,943 @@
1/* $OpenBSD: ecp_hp_methods.c,v 1.5 2025/08/03 15:44:00 jsing Exp $ */
2/*
3 * Copyright (c) 2024-2025 Joel Sing <jsing@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <string.h>
19
20#include <openssl/bn.h>
21#include <openssl/ec.h>
22#include <openssl/err.h>
23
24#include "bn_internal.h"
25#include "crypto_internal.h"
26#include "ec_local.h"
27#include "ec_internal.h"
28#include "err_local.h"
29
30static int
31ec_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
32 const BIGNUM *b, BN_CTX *ctx)
33{
34 BIGNUM *t;
35 int ret = 0;
36
37 BN_CTX_start(ctx);
38
39 /* XXX - p must be a prime > 3. */
40
41 if (!bn_copy(group->p, p))
42 goto err;
43 if (!bn_copy(group->a, a))
44 goto err;
45 if (!bn_copy(group->b, b))
46 goto err;
47
48 /* XXX */
49 BN_set_negative(group->p, 0);
50
51 /* XXX */
52 if (!BN_nnmod(group->a, group->a, group->p, ctx))
53 goto err;
54 if (!BN_nnmod(group->b, group->b, group->p, ctx))
55 goto err;
56
57 if ((t = BN_CTX_get(ctx)) == NULL)
58 goto err;
59 if (!BN_set_word(t, 3))
60 goto err;
61 if (!BN_mod_add(t, t, a, group->p, ctx))
62 goto err;
63
64 group->a_is_minus3 = BN_is_zero(t);
65
66 if (!ec_field_modulus_from_bn(&group->fm, group->p, ctx))
67 goto err;
68 if (!ec_field_element_from_bn(&group->fm, group, &group->fe_a, group->a, ctx))
69 goto err;
70 if (!ec_field_element_from_bn(&group->fm, group, &group->fe_b, group->b, ctx))
71 goto err;
72
73 ret = 1;
74
75 err:
76 BN_CTX_end(ctx);
77
78 return ret;
79}
80
81static int
82ec_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
83 BIGNUM *b, BN_CTX *ctx)
84{
85 if (p != NULL) {
86 if (!bn_copy(p, group->p))
87 return 0;
88 }
89 if (a != NULL) {
90 if (!bn_copy(a, group->a))
91 return 0;
92 }
93 if (b != NULL) {
94 if (!bn_copy(b, group->b))
95 return 0;
96 }
97 return 1;
98}
99
100static int
101ec_point_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
102{
103 /* Check if Z is equal to zero. */
104 return ec_field_element_is_zero(&group->fm, &point->fe_z);
105}
106
107static int
108ec_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
109{
110 /* Infinity is (x = 0, y = 1, z = 0). */
111
112 memset(&point->fe_x, 0, sizeof(point->fe_x));
113 memset(&point->fe_y, 0, sizeof(point->fe_y));
114 memset(&point->fe_z, 0, sizeof(point->fe_z));
115
116 point->fe_y.w[0] = 1;
117
118 return 1;
119}
120
121static int
122ec_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
123 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
124{
125 if (x == NULL || y == NULL) {
126 ECerror(ERR_R_PASSED_NULL_PARAMETER);
127 return 0;
128 }
129
130 if (!bn_copy(point->X, x))
131 return 0;
132 if (!bn_copy(point->Y, y))
133 return 0;
134 if (!BN_one(point->Z))
135 return 0;
136
137 /* XXX */
138 if (!BN_nnmod(point->X, point->X, group->p, ctx))
139 return 0;
140 if (!BN_nnmod(point->Y, point->Y, group->p, ctx))
141 return 0;
142
143 if (!ec_field_element_from_bn(&group->fm, group, &point->fe_x, point->X, ctx))
144 return 0;
145 if (!ec_field_element_from_bn(&group->fm, group, &point->fe_y, point->Y, ctx))
146 return 0;
147 if (!ec_field_element_from_bn(&group->fm, group, &point->fe_z, point->Z, ctx))
148 return 0;
149
150 return 1;
151}
152
153static int
154ec_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
155 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
156{
157 BIGNUM *zinv;
158 int ret = 0;
159
160 /*
161 * Convert homogeneous projective coordinates (XZ, YZ, Z) to affine
162 * coordinates (x = X/Z, y = Y/Z).
163 */
164 if (!ec_field_element_to_bn(&group->fm, &point->fe_x, point->X, ctx))
165 return 0;
166 if (!ec_field_element_to_bn(&group->fm, &point->fe_y, point->Y, ctx))
167 return 0;
168 if (!ec_field_element_to_bn(&group->fm, &point->fe_z, point->Z, ctx))
169 return 0;
170
171 BN_CTX_start(ctx);
172
173 if ((zinv = BN_CTX_get(ctx)) == NULL)
174 goto err;
175
176 if (BN_mod_inverse_ct(zinv, point->Z, group->p, ctx) == NULL)
177 goto err;
178
179 if (x != NULL) {
180 if (!BN_mod_mul(x, point->X, zinv, group->p, ctx))
181 goto err;
182 }
183 if (y != NULL) {
184 if (!BN_mod_mul(y, point->Y, zinv, group->p, ctx))
185 goto err;
186 }
187
188 ret = 1;
189
190 err:
191 BN_CTX_end(ctx);
192
193 return ret;
194}
195
196static int
197ec_point_add_a1(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
198 const EC_POINT *b, BN_CTX *ctx)
199{
200 EC_FIELD_ELEMENT X1, Y1, Z1, X2, Y2, Z2, X3, Y3, Z3;
201 EC_FIELD_ELEMENT b3, t0, t1, t2, t3, t4, t5;
202 EC_FIELD_ELEMENT ga, gb;
203
204 /*
205 * Complete, projective point addition for arbitrary prime order short
206 * Weierstrass curves with arbitrary a - see
207 * https://eprint.iacr.org/2015/1060, algorithm 1 and appendix A.1.
208 */
209
210 ec_field_element_copy(&ga, &group->fe_a);
211 ec_field_element_copy(&gb, &group->fe_b);
212
213 ec_field_element_copy(&X1, &a->fe_x);
214 ec_field_element_copy(&Y1, &a->fe_y);
215 ec_field_element_copy(&Z1, &a->fe_z);
216
217 ec_field_element_copy(&X2, &b->fe_x);
218 ec_field_element_copy(&Y2, &b->fe_y);
219 ec_field_element_copy(&Z2, &b->fe_z);
220
221 /* b3 := 3 * b ; */
222 ec_field_element_add(&group->fm, &b3, &gb, &gb);
223 ec_field_element_add(&group->fm, &b3, &b3, &gb);
224
225 /* t0 := X1 * X2 ; t1 := Y1 * Y2 ; t2 := Z1 * Z2 ; */
226 ec_field_element_mul(&group->fm, &t0, &X1, &X2);
227 ec_field_element_mul(&group->fm, &t1, &Y1, &Y2);
228 ec_field_element_mul(&group->fm, &t2, &Z1, &Z2);
229
230 /* t3 := X1 + Y1 ; t4 := X2 + Y2 ; t3 := t3 * t4 ; */
231 ec_field_element_add(&group->fm, &t3, &X1, &Y1);
232 ec_field_element_add(&group->fm, &t4, &X2, &Y2);
233 ec_field_element_mul(&group->fm, &t3, &t3, &t4);
234
235 /* t4 := t0 + t1 ; t3 := t3 - t4 ; t4 := X1 + Z1 ; */
236 ec_field_element_add(&group->fm, &t4, &t0, &t1);
237 ec_field_element_sub(&group->fm, &t3, &t3, &t4);
238 ec_field_element_add(&group->fm, &t4, &X1, &Z1);
239
240 /* t5 := X2 + Z2 ; t4 := t4 * t5 ; t5 := t0 + t2 ; */
241 ec_field_element_add(&group->fm, &t5, &X2, &Z2);
242 ec_field_element_mul(&group->fm, &t4, &t4, &t5);
243 ec_field_element_add(&group->fm, &t5, &t0, &t2);
244
245 /* t4 := t4 - t5 ; t5 := Y1 + Z1 ; X3 := Y2 + Z2 ; */
246 ec_field_element_sub(&group->fm, &t4, &t4, &t5);
247 ec_field_element_add(&group->fm, &t5, &Y1, &Z1);
248 ec_field_element_add(&group->fm, &X3, &Y2, &Z2);
249
250 /* t5 := t5 * X3 ; X3 := t1 + t2 ; t5 := t5 - X3 ; */
251 ec_field_element_mul(&group->fm, &t5, &t5, &X3);
252 ec_field_element_add(&group->fm, &X3, &t1, &t2);
253 ec_field_element_sub(&group->fm, &t5, &t5, &X3);
254
255 /* Z3 := a * t4 ; X3 := b3 * t2 ; Z3 := X3 + Z3 ; */
256 ec_field_element_mul(&group->fm, &Z3, &ga, &t4);
257 ec_field_element_mul(&group->fm, &X3, &b3, &t2);
258 ec_field_element_add(&group->fm, &Z3, &X3, &Z3);
259
260 /* X3 := t1 - Z3 ; Z3 := t1 + Z3 ; Y3 := X3 * Z3 ; */
261 ec_field_element_sub(&group->fm, &X3, &t1, &Z3);
262 ec_field_element_add(&group->fm, &Z3, &t1, &Z3);
263 ec_field_element_mul(&group->fm, &Y3, &X3, &Z3);
264
265 /* t1 := t0 + t0 ; t1 := t1 + t0 ; t2 := a * t2 ; */
266 ec_field_element_add(&group->fm, &t1, &t0, &t0);
267 ec_field_element_add(&group->fm, &t1, &t1, &t0);
268 ec_field_element_mul(&group->fm, &t2, &ga, &t2);
269
270 /* t4 := b3 * t4 ; t1 := t1 + t2 ; t2 := t0 - t2 ; */
271 ec_field_element_mul(&group->fm, &t4, &b3, &t4);
272 ec_field_element_add(&group->fm, &t1, &t1, &t2);
273 ec_field_element_sub(&group->fm, &t2, &t0, &t2);
274
275 /* t2 := a * t2 ; t4 := t4 + t2 ; t0 := t1 * t4 ; */
276 ec_field_element_mul(&group->fm, &t2, &ga, &t2);
277 ec_field_element_add(&group->fm, &t4, &t4, &t2);
278 ec_field_element_mul(&group->fm, &t0, &t1, &t4);
279
280 /* Y3 := Y3 + t0 ; t0 := t5 * t4 ; X3 := t3 * X3 ; */
281 ec_field_element_add(&group->fm, &Y3, &Y3, &t0);
282 ec_field_element_mul(&group->fm, &t0, &t5, &t4);
283 ec_field_element_mul(&group->fm, &X3, &t3, &X3);
284
285 /* X3 := X3 - t0 ; t0 := t3 * t1 ; Z3 := t5 * Z3 ; */
286 ec_field_element_sub(&group->fm, &X3, &X3, &t0);
287 ec_field_element_mul(&group->fm, &t0, &t3, &t1);
288 ec_field_element_mul(&group->fm, &Z3, &t5, &Z3);
289
290 /* Z3 := Z3 + t0 ; */
291 ec_field_element_add(&group->fm, &Z3, &Z3, &t0);
292
293 ec_field_element_copy(&r->fe_x, &X3);
294 ec_field_element_copy(&r->fe_y, &Y3);
295 ec_field_element_copy(&r->fe_z, &Z3);
296
297 return 1;
298}
299
300static int
301ec_point_add_a2(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
302 const EC_POINT *b, BN_CTX *ctx)
303{
304 EC_FIELD_ELEMENT X1, Y1, Z1, X2, Y2, Z2, X3, Y3, Z3;
305 EC_FIELD_ELEMENT t0, t1, t2, t3, t4;
306 EC_FIELD_ELEMENT gb;
307
308 /*
309 * Complete, projective point addition for arbitrary prime order short
310 * Weierstrass curves with a = -3 - see https://eprint.iacr.org/2015/1060,
311 * algorithm 4 and appendix A.2.
312 */
313
314 ec_field_element_copy(&gb, &group->fe_b);
315
316 ec_field_element_copy(&X1, &a->fe_x);
317 ec_field_element_copy(&Y1, &a->fe_y);
318 ec_field_element_copy(&Z1, &a->fe_z);
319
320 ec_field_element_copy(&X2, &b->fe_x);
321 ec_field_element_copy(&Y2, &b->fe_y);
322 ec_field_element_copy(&Z2, &b->fe_z);
323
324 /* t0 := X1 * X2 ; t1 := Y1 * Y2 ; t2 := Z1 * Z2 ; */
325 ec_field_element_mul(&group->fm, &t0, &X1, &X2);
326 ec_field_element_mul(&group->fm, &t1, &Y1, &Y2);
327 ec_field_element_mul(&group->fm, &t2, &Z1, &Z2);
328
329 /* t3 := X1 + Y1 ; t4 := X2 + Y2 ; t3 := t3 * t4 ; */
330 ec_field_element_add(&group->fm, &t3, &X1, &Y1);
331 ec_field_element_add(&group->fm, &t4, &X2, &Y2);
332 ec_field_element_mul(&group->fm, &t3, &t3, &t4);
333
334 /* t4 := t0 + t1 ; t3 := t3 - t4 ; t4 := Y1 + Z1 ; */
335 ec_field_element_add(&group->fm, &t4, &t0, &t1);
336 ec_field_element_sub(&group->fm, &t3, &t3, &t4);
337 ec_field_element_add(&group->fm, &t4, &Y1, &Z1);
338
339 /* X3 := Y2 + Z2 ; t4 := t4 * X3 ; X3 := t1 + t2 ; */
340 ec_field_element_add(&group->fm, &X3, &Y2, &Z2);
341 ec_field_element_mul(&group->fm, &t4, &t4, &X3);
342 ec_field_element_add(&group->fm, &X3, &t1, &t2);
343
344 /* t4 := t4 - X3 ; X3 := X1 + Z1 ; Y3 := X2 + Z2 ; */
345 ec_field_element_sub(&group->fm, &t4, &t4, &X3);
346 ec_field_element_add(&group->fm, &X3, &X1, &Z1);
347 ec_field_element_add(&group->fm, &Y3, &X2, &Z2);
348
349 /* X3 := X3 * Y3 ; Y3 := t0 + t2 ; Y3 := X3 - Y3 ; */
350 ec_field_element_mul(&group->fm, &X3, &X3, &Y3);
351 ec_field_element_add(&group->fm, &Y3, &t0, &t2);
352 ec_field_element_sub(&group->fm, &Y3, &X3, &Y3);
353
354 /* Z3 := b * t2 ; X3 := Y3 - Z3 ; Z3 := X3 + X3 ; */
355 ec_field_element_mul(&group->fm, &Z3, &gb, &t2);
356 ec_field_element_sub(&group->fm, &X3, &Y3, &Z3);
357 ec_field_element_add(&group->fm, &Z3, &X3, &X3);
358
359 /* X3 := X3 + Z3 ; Z3 := t1 - X3 ; X3 := t1 + X3 ; */
360 ec_field_element_add(&group->fm, &X3, &X3, &Z3);
361 ec_field_element_sub(&group->fm, &Z3, &t1, &X3);
362 ec_field_element_add(&group->fm, &X3, &t1, &X3);
363
364 /* Y3 := b * Y3 ; t1 := t2 + t2 ; t2 := t1 + t2 ; */
365 ec_field_element_mul(&group->fm, &Y3, &gb, &Y3);
366 ec_field_element_add(&group->fm, &t1, &t2, &t2);
367 ec_field_element_add(&group->fm, &t2, &t1, &t2);
368
369 /* Y3 := Y3 - t2 ; Y3 := Y3 - t0 ; t1 := Y3 + Y3 ; */
370 ec_field_element_sub(&group->fm, &Y3, &Y3, &t2);
371 ec_field_element_sub(&group->fm, &Y3, &Y3, &t0);
372 ec_field_element_add(&group->fm, &t1, &Y3, &Y3);
373
374 /* Y3 := t1 + Y3 ; t1 := t0 + t0 ; t0 := t1 + t0 ; */
375 ec_field_element_add(&group->fm, &Y3, &t1, &Y3);
376 ec_field_element_add(&group->fm, &t1, &t0, &t0);
377 ec_field_element_add(&group->fm, &t0, &t1, &t0);
378
379 /* t0 := t0 - t2 ; t1 := t4 * Y3 ; t2 := t0 * Y3 ; */
380 ec_field_element_sub(&group->fm, &t0, &t0, &t2);
381 ec_field_element_mul(&group->fm, &t1, &t4, &Y3);
382 ec_field_element_mul(&group->fm, &t2, &t0, &Y3);
383
384 /* Y3 := X3 * Z3 ; Y3 := Y3 + t2 ; X3 := t3 * X3 ; */
385 ec_field_element_mul(&group->fm, &Y3, &X3, &Z3);
386 ec_field_element_add(&group->fm, &Y3, &Y3, &t2);
387 ec_field_element_mul(&group->fm, &X3, &t3, &X3);
388
389 /* X3 := X3 - t1 ; Z3 := t4 * Z3 ; t1 := t3 * t0 ; */
390 ec_field_element_sub(&group->fm, &X3, &X3, &t1);
391 ec_field_element_mul(&group->fm, &Z3, &t4, &Z3);
392 ec_field_element_mul(&group->fm, &t1, &t3, &t0);
393
394 /* Z3 := Z3 + t1 ; */
395 ec_field_element_add(&group->fm, &Z3, &Z3, &t1);
396
397 ec_field_element_copy(&r->fe_x, &X3);
398 ec_field_element_copy(&r->fe_y, &Y3);
399 ec_field_element_copy(&r->fe_z, &Z3);
400
401 return 1;
402}
403
404static int
405ec_point_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
406 const EC_POINT *b, BN_CTX *ctx)
407{
408 if (group->a_is_minus3)
409 return ec_point_add_a2(group, r, a, b, ctx);
410
411 return ec_point_add_a1(group, r, a, b, ctx);
412}
413
414static int
415ec_point_dbl_a1(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
416{
417 EC_FIELD_ELEMENT X1, Y1, Z1, X3, Y3, Z3;
418 EC_FIELD_ELEMENT b3, t0, t1, t2, t3;
419 EC_FIELD_ELEMENT ga, gb;
420
421 /*
422 * Exception-free point doubling for arbitrary prime order short
423 * Weierstrass curves with arbitrary a - see
424 * https://eprint.iacr.org/2015/1060, algorithm 3 and appendix A.1.
425 */
426
427 ec_field_element_copy(&ga, &group->fe_a);
428 ec_field_element_copy(&gb, &group->fe_b);
429
430 ec_field_element_copy(&X1, &a->fe_x);
431 ec_field_element_copy(&Y1, &a->fe_y);
432 ec_field_element_copy(&Z1, &a->fe_z);
433
434 /* b3 := 3 * b ; */
435 ec_field_element_add(&group->fm, &b3, &gb, &gb);
436 ec_field_element_add(&group->fm, &b3, &b3, &gb);
437
438 /* t0 := X^2; t1 := Y^2; t2 := Z^2 ; */
439 ec_field_element_sqr(&group->fm, &t0, &X1);
440 ec_field_element_sqr(&group->fm, &t1, &Y1);
441 ec_field_element_sqr(&group->fm, &t2, &Z1);
442
443 /* t3 := X * Y ; t3 := t3 + t3 ; Z3 := X * Z ; */
444 ec_field_element_mul(&group->fm, &t3, &X1, &Y1);
445 ec_field_element_add(&group->fm, &t3, &t3, &t3);
446 ec_field_element_mul(&group->fm, &Z3, &X1, &Z1);
447
448 /* Z3 := Z3 + Z3 ; X3 := a * Z3 ; Y3 := b3 * t2 ; */
449 ec_field_element_add(&group->fm, &Z3, &Z3, &Z3);
450 ec_field_element_mul(&group->fm, &X3, &ga, &Z3);
451 ec_field_element_mul(&group->fm, &Y3, &b3, &t2);
452
453 /* Y3 := X3 + Y3 ; X3 := t1 - Y3 ; Y3 := t1 + Y3 ; */
454 ec_field_element_add(&group->fm, &Y3, &X3, &Y3);
455 ec_field_element_sub(&group->fm, &X3, &t1, &Y3);
456 ec_field_element_add(&group->fm, &Y3, &t1, &Y3);
457
458 /* Y3 := X3 * Y3 ; X3 := t3 * X3 ; Z3 := b3 * Z3 ; */
459 ec_field_element_mul(&group->fm, &Y3, &X3, &Y3);
460 ec_field_element_mul(&group->fm, &X3, &t3, &X3);
461 ec_field_element_mul(&group->fm, &Z3, &b3, &Z3);
462
463 /* t2 := a * t2 ; t3 := t0 - t2 ; t3 := a * t3 ; */
464 ec_field_element_mul(&group->fm, &t2, &ga, &t2);
465 ec_field_element_sub(&group->fm, &t3, &t0, &t2);
466 ec_field_element_mul(&group->fm, &t3, &ga, &t3);
467
468 /* t3 := t3 + Z3 ; Z3 := t0 + t0 ; t0 := Z3 + t0 ; */
469 ec_field_element_add(&group->fm, &t3, &t3, &Z3);
470 ec_field_element_add(&group->fm, &Z3, &t0, &t0);
471 ec_field_element_add(&group->fm, &t0, &Z3, &t0);
472
473 /* t0 := t0 + t2 ; t0 := t0 * t3 ; Y3 := Y3 + t0 ; */
474 ec_field_element_add(&group->fm, &t0, &t0, &t2);
475 ec_field_element_mul(&group->fm, &t0, &t0, &t3);
476 ec_field_element_add(&group->fm, &Y3, &Y3, &t0);
477
478 /* t2 := Y * Z ; t2 := t2 + t2 ; t0 := t2 * t3 ; */
479 ec_field_element_mul(&group->fm, &t2, &Y1, &Z1);
480 ec_field_element_add(&group->fm, &t2, &t2, &t2);
481 ec_field_element_mul(&group->fm, &t0, &t2, &t3);
482
483 /* X3 := X3 - t0 ; Z3 := t2 * t1 ; Z3 := Z3 + Z3 ; */
484 ec_field_element_sub(&group->fm, &X3, &X3, &t0);
485 ec_field_element_mul(&group->fm, &Z3, &t2, &t1);
486 ec_field_element_add(&group->fm, &Z3, &Z3, &Z3);
487
488 /* Z3 := Z3 + Z3 ; */
489 ec_field_element_add(&group->fm, &Z3, &Z3, &Z3);
490
491 ec_field_element_copy(&r->fe_x, &X3);
492 ec_field_element_copy(&r->fe_y, &Y3);
493 ec_field_element_copy(&r->fe_z, &Z3);
494
495 return 1;
496}
497
498static int
499ec_point_dbl_a2(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
500{
501 EC_FIELD_ELEMENT X1, Y1, Z1, X3, Y3, Z3;
502 EC_FIELD_ELEMENT t0, t1, t2, t3;
503 EC_FIELD_ELEMENT ga, gb;
504
505 /*
506 * Exception-free point doubling for arbitrary prime order short
507 * Weierstrass curves with a = -3 - see https://eprint.iacr.org/2015/1060,
508 * algorithm 6 and appendix A.2.
509 */
510
511 ec_field_element_copy(&ga, &group->fe_a);
512 ec_field_element_copy(&gb, &group->fe_b);
513
514 ec_field_element_copy(&X1, &a->fe_x);
515 ec_field_element_copy(&Y1, &a->fe_y);
516 ec_field_element_copy(&Z1, &a->fe_z);
517
518 /* t0 := X^2; t1 := Y^2; t2 := Z^2 ; */
519 ec_field_element_sqr(&group->fm, &t0, &X1);
520 ec_field_element_sqr(&group->fm, &t1, &Y1);
521 ec_field_element_sqr(&group->fm, &t2, &Z1);
522
523 /* t3 := X * Y ; t3 := t3 + t3 ; Z3 := X * Z ; */
524 ec_field_element_mul(&group->fm, &t3, &X1, &Y1);
525 ec_field_element_add(&group->fm, &t3, &t3, &t3);
526 ec_field_element_mul(&group->fm, &Z3, &X1, &Z1);
527
528 /* Z3 := Z3 + Z3 ; Y3 := b * t2 ; Y3 := Y3 - Z3 ; */
529 ec_field_element_add(&group->fm, &Z3, &Z3, &Z3);
530 ec_field_element_mul(&group->fm, &Y3, &gb, &t2);
531 ec_field_element_sub(&group->fm, &Y3, &Y3, &Z3);
532
533 /* X3 := Y3 + Y3 ; Y3 := X3 + Y3 ; X3 := t1 - Y3 ; */
534 ec_field_element_add(&group->fm, &X3, &Y3, &Y3);
535 ec_field_element_add(&group->fm, &Y3, &X3, &Y3);
536 ec_field_element_sub(&group->fm, &X3, &t1, &Y3);
537
538 /* Y3 := t1 + Y3 ; Y3 := X3 * Y3 ; X3 := X3 * t3 ; */
539 ec_field_element_add(&group->fm, &Y3, &t1, &Y3);
540 ec_field_element_mul(&group->fm, &Y3, &X3, &Y3);
541 ec_field_element_mul(&group->fm, &X3, &X3, &t3);
542
543 /* t3 := t2 + t2 ; t2 := t2 + t3 ; Z3 := b * Z3 ; */
544 ec_field_element_add(&group->fm, &t3, &t2, &t2);
545 ec_field_element_add(&group->fm, &t2, &t2, &t3);
546 ec_field_element_mul(&group->fm, &Z3, &gb, &Z3);
547
548 /* Z3 := Z3 - t2 ; Z3 := Z3 - t0 ; t3 := Z3 + Z3 ; */
549 ec_field_element_sub(&group->fm, &Z3, &Z3, &t2);
550 ec_field_element_sub(&group->fm, &Z3, &Z3, &t0);
551 ec_field_element_add(&group->fm, &t3, &Z3, &Z3);
552
553 /* Z3 := Z3 + t3 ; t3 := t0 + t0 ; t0 := t3 + t0 ; */
554 ec_field_element_add(&group->fm, &Z3, &Z3, &t3);
555 ec_field_element_add(&group->fm, &t3, &t0, &t0);
556 ec_field_element_add(&group->fm, &t0, &t3, &t0);
557
558 /* t0 := t0 - t2 ; t0 := t0 * Z3 ; Y3 := Y3 + t0 ; */
559 ec_field_element_sub(&group->fm, &t0, &t0, &t2);
560 ec_field_element_mul(&group->fm, &t0, &t0, &Z3);
561 ec_field_element_add(&group->fm, &Y3, &Y3, &t0);
562
563 /* t0 := Y * Z ; t0 := t0 + t0 ; Z3 := t0 * Z3 ; */
564 ec_field_element_mul(&group->fm, &t0, &Y1, &Z1);
565 ec_field_element_add(&group->fm, &t0, &t0, &t0);
566 ec_field_element_mul(&group->fm, &Z3, &t0, &Z3);
567
568 /* X3 := X3 - Z3 ; Z3 := t0 * t1 ; Z3 := Z3 + Z3 ; */
569 ec_field_element_sub(&group->fm, &X3, &X3, &Z3);
570 ec_field_element_mul(&group->fm, &Z3, &t0, &t1);
571 ec_field_element_add(&group->fm, &Z3, &Z3, &Z3);
572
573 /* Z3 := Z3 + Z3 ; */
574 ec_field_element_add(&group->fm, &Z3, &Z3, &Z3);
575
576 ec_field_element_copy(&r->fe_x, &X3);
577 ec_field_element_copy(&r->fe_y, &Y3);
578 ec_field_element_copy(&r->fe_z, &Z3);
579
580 return 1;
581}
582
583static int
584ec_point_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
585{
586 if (group->a_is_minus3)
587 return ec_point_dbl_a2(group, r, a, ctx);
588
589 return ec_point_dbl_a1(group, r, a, ctx);
590}
591
592static int
593ec_point_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
594{
595 EC_FIELD_ELEMENT y;
596 BN_ULONG mask;
597 int i;
598
599 /*
600 * Invert the point by setting Y = p - Y, if Y is non-zero and the point
601 * is not at infinity.
602 */
603
604 mask = ~(0 - (ec_point_is_at_infinity(group, point) |
605 ec_field_element_is_zero(&group->fm, &point->fe_y)));
606
607 /* XXX - masked/conditional subtraction? */
608 ec_field_element_sub(&group->fm, &y, &group->fm.m, &point->fe_y);
609
610 for (i = 0; i < group->fm.n; i++)
611 point->fe_y.w[i] = (point->fe_y.w[i] & ~mask) | (y.w[i] & mask);
612
613 return 1;
614}
615
616static int
617ec_point_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
618{
619 EC_FIELD_ELEMENT sum, axz2, bz3, x3, y2z, z2;
620
621 /*
622 * Curve is defined by a Weierstrass equation y^2 = x^3 + a*x + b.
623 * The given point is in homogeneous projective coordinates
624 * (x = X/Z, y = Y/Z). Substitute and multiply by Z^3 in order to
625 * evaluate as zy^2 = x^3 + axz^2 + bz^3.
626 */
627
628 ec_field_element_sqr(&group->fm, &z2, &point->fe_z);
629
630 ec_field_element_sqr(&group->fm, &y2z, &point->fe_y);
631 ec_field_element_mul(&group->fm, &y2z, &y2z, &point->fe_z);
632
633 ec_field_element_sqr(&group->fm, &x3, &point->fe_x);
634 ec_field_element_mul(&group->fm, &x3, &x3, &point->fe_x);
635
636 ec_field_element_mul(&group->fm, &axz2, &group->fe_a, &point->fe_x);
637 ec_field_element_mul(&group->fm, &axz2, &axz2, &z2);
638
639 ec_field_element_mul(&group->fm, &bz3, &group->fe_b, &point->fe_z);
640 ec_field_element_mul(&group->fm, &bz3, &bz3, &z2);
641
642 ec_field_element_add(&group->fm, &sum, &x3, &axz2);
643 ec_field_element_add(&group->fm, &sum, &sum, &bz3);
644
645 return ec_field_element_equal(&group->fm, &y2z, &sum) |
646 ec_point_is_at_infinity(group, point);
647}
648
649static int
650ec_point_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
651{
652 EC_FIELD_ELEMENT ax, ay, bx, by;
653
654 /*
655 * Compare two points that have homogeneous projection coordinates, that
656 * is (X_a/Z_a, Y_a/Z_a) == (X_b/Z_b, Y_b/Z_b). Return -1 on error, 0 on
657 * equality and 1 on inequality.
658 *
659 * If a and b are both at infinity, Z_a and Z_b will both be zero,
660 * resulting in all values becoming zero, resulting in equality. If a is
661 * at infinity and b is not, then Y_a will be one and Z_b will be
662 * non-zero, hence Y_a * Z_b will be non-zero. Z_a will be zero, hence
663 * Y_b * Z_a will be zero, resulting in inequality. The same applies if
664 * b is at infinity and a is not.
665 */
666
667 ec_field_element_mul(&group->fm, &ax, &a->fe_x, &b->fe_z);
668 ec_field_element_mul(&group->fm, &ay, &a->fe_y, &b->fe_z);
669 ec_field_element_mul(&group->fm, &bx, &b->fe_x, &a->fe_z);
670 ec_field_element_mul(&group->fm, &by, &b->fe_y, &a->fe_z);
671
672 return 1 - (ec_field_element_equal(&group->fm, &ax, &bx) &
673 ec_field_element_equal(&group->fm, &ay, &by));
674}
675
676#if 0
677static int
678ec_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[],
679 BN_CTX *ctx)
680{
681 size_t i;
682
683 /* XXX */
684 for (i = 0; i < num; i++) {
685 if (!EC_POINT_make_affine(group, points[0], ctx))
686 return 0;
687 }
688
689 return 1;
690}
691#else
692
693static int
694ec_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[],
695 BN_CTX *ctx)
696{
697 BIGNUM **prod_Z = NULL;
698 BIGNUM *tmp, *tmp_Z;
699 size_t i;
700 int ret = 0;
701
702 if (num == 0)
703 return 1;
704
705 BN_CTX_start(ctx);
706
707 if ((tmp = BN_CTX_get(ctx)) == NULL)
708 goto err;
709 if ((tmp_Z = BN_CTX_get(ctx)) == NULL)
710 goto err;
711
712 if ((prod_Z = calloc(num, sizeof *prod_Z)) == NULL)
713 goto err;
714 for (i = 0; i < num; i++) {
715 if ((prod_Z[i] = BN_CTX_get(ctx)) == NULL)
716 goto err;
717 }
718
719 if (!BN_is_zero(points[0]->Z)) {
720 if (!bn_copy(prod_Z[0], points[0]->Z))
721 goto err;
722 } else {
723 if (!BN_one(prod_Z[0]))
724 goto err;
725 }
726
727 for (i = 1; i < num; i++) {
728 if (!BN_is_zero(points[i]->Z)) {
729 if (!BN_mod_mul(prod_Z[i], prod_Z[i - 1], points[i]->Z,
730 group->p, ctx))
731 goto err;
732 } else {
733 if (!bn_copy(prod_Z[i], prod_Z[i - 1]))
734 goto err;
735 }
736 }
737
738 if (!BN_mod_inverse_nonct(tmp, prod_Z[num - 1], group->p, ctx)) {
739 ECerror(ERR_R_BN_LIB);
740 goto err;
741 }
742
743 for (i = num - 1; i > 0; i--) {
744 if (BN_is_zero(points[i]->Z))
745 continue;
746
747 if (!BN_mod_mul(tmp_Z, prod_Z[i - 1], tmp, group->p, ctx))
748 goto err;
749 if (!BN_mod_mul(tmp, tmp, points[i]->Z, group->p, ctx))
750 goto err;
751 if (!bn_copy(points[i]->Z, tmp_Z))
752 goto err;
753 }
754
755 for (i = 0; i < num; i++) {
756 EC_POINT *p = points[i];
757
758 if (BN_is_zero(p->Z))
759 continue;
760
761 if (!BN_mod_mul(p->X, p->X, p->Z, group->p, ctx))
762 goto err;
763 if (!BN_mod_mul(p->Y, p->Y, p->Z, group->p, ctx))
764 goto err;
765
766 if (!BN_one(p->Z))
767 goto err;
768 }
769
770 ret = 1;
771
772 err:
773 BN_CTX_end(ctx);
774 free(prod_Z);
775
776 return ret;
777}
778#endif
779
780static void
781ec_point_select(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
782 const EC_POINT *b, int conditional)
783{
784 ec_field_element_select(&group->fm, &r->fe_x, &a->fe_x, &b->fe_x, conditional);
785 ec_field_element_select(&group->fm, &r->fe_y, &a->fe_y, &b->fe_y, conditional);
786 ec_field_element_select(&group->fm, &r->fe_z, &a->fe_z, &b->fe_z, conditional);
787}
788
789static int
790ec_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, const EC_POINT *point,
791 BN_CTX *ctx)
792{
793 BIGNUM *cardinality;
794 EC_POINT *multiples[15];
795 EC_POINT *rr = NULL, *t = NULL;
796 uint8_t *scalar_bytes = NULL;
797 int scalar_len = 0;
798 uint8_t j, wv;
799 int conditional, i;
800 int ret = 0;
801
802 memset(multiples, 0, sizeof(multiples));
803
804 BN_CTX_start(ctx);
805
806 /* XXX - consider blinding. */
807
808 if ((cardinality = BN_CTX_get(ctx)) == NULL)
809 goto err;
810 if (!BN_mul(cardinality, group->order, group->cofactor, ctx))
811 goto err;
812
813 /* XXX - handle scalar > cardinality and/or negative. */
814
815 /* Convert scalar into big endian bytes. */
816 scalar_len = BN_num_bytes(cardinality);
817 if ((scalar_bytes = calloc(1, scalar_len)) == NULL)
818 goto err;
819 if (!BN_bn2binpad(scalar, scalar_bytes, scalar_len))
820 goto err;
821
822 /* Compute multiples of point. */
823 if ((multiples[0] = EC_POINT_dup(point, group)) == NULL)
824 goto err;
825 for (i = 1; i < 15; i += 2) {
826 if ((multiples[i] = EC_POINT_new(group)) == NULL)
827 goto err;
828 if (!EC_POINT_dbl(group, multiples[i], multiples[i / 2], ctx))
829 goto err;
830 if ((multiples[i + 1] = EC_POINT_new(group)) == NULL)
831 goto err;
832 if (!EC_POINT_add(group, multiples[i + 1], multiples[i], point, ctx))
833 goto err;
834 }
835
836 if ((rr = EC_POINT_new(group)) == NULL)
837 goto err;
838 if ((t = EC_POINT_new(group)) == NULL)
839 goto err;
840
841 if (!EC_POINT_set_to_infinity(group, rr))
842 goto err;
843
844 for (i = 0; i < scalar_len; i++) {
845 if (i != 0) {
846 if (!EC_POINT_dbl(group, rr, rr, ctx))
847 goto err;
848 if (!EC_POINT_dbl(group, rr, rr, ctx))
849 goto err;
850 if (!EC_POINT_dbl(group, rr, rr, ctx))
851 goto err;
852 if (!EC_POINT_dbl(group, rr, rr, ctx))
853 goto err;
854 }
855
856 if (!EC_POINT_set_to_infinity(group, t))
857 goto err;
858
859 wv = scalar_bytes[i] >> 4;
860 for (j = 1; j < 16; j++) {
861 conditional = crypto_ct_eq_u8(j, wv);
862 ec_point_select(group, t, t, multiples[j - 1], conditional);
863 }
864 if (!EC_POINT_add(group, rr, rr, t, ctx))
865 goto err;
866
867 if (!EC_POINT_dbl(group, rr, rr, ctx))
868 goto err;
869 if (!EC_POINT_dbl(group, rr, rr, ctx))
870 goto err;
871 if (!EC_POINT_dbl(group, rr, rr, ctx))
872 goto err;
873 if (!EC_POINT_dbl(group, rr, rr, ctx))
874 goto err;
875
876 if (!EC_POINT_set_to_infinity(group, t))
877 goto err;
878
879 wv = scalar_bytes[i] & 0xf;
880 for (j = 1; j < 16; j++) {
881 conditional = crypto_ct_eq_u8(j, wv);
882 ec_point_select(group, t, t, multiples[j - 1], conditional);
883 }
884 if (!EC_POINT_add(group, rr, rr, t, ctx))
885 goto err;
886 }
887
888 if (!EC_POINT_copy(r, rr))
889 goto err;
890
891 ret = 1;
892
893 err:
894 for (i = 0; i < 15; i++)
895 EC_POINT_free(multiples[i]);
896
897 EC_POINT_free(rr);
898 EC_POINT_free(t);
899
900 freezero(scalar_bytes, scalar_len);
901
902 BN_CTX_end(ctx);
903
904 return ret;
905}
906
907static int
908ec_mul_single_ct(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
909 const EC_POINT *point, BN_CTX *ctx)
910{
911 return ec_mul(group, r, scalar, point, ctx);
912}
913
914static int
915ec_mul_double_nonct(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar1,
916 const EC_POINT *point1, const BIGNUM *scalar2, const EC_POINT *point2,
917 BN_CTX *ctx)
918{
919 return ec_wnaf_mul(group, r, scalar1, point1, scalar2, point2, ctx);
920}
921
922static const EC_METHOD ec_GFp_homogeneous_projective_method = {
923 .group_set_curve = ec_group_set_curve,
924 .group_get_curve = ec_group_get_curve,
925 .point_set_to_infinity = ec_point_set_to_infinity,
926 .point_is_at_infinity = ec_point_is_at_infinity,
927 .point_set_affine_coordinates = ec_point_set_affine_coordinates,
928 .point_get_affine_coordinates = ec_point_get_affine_coordinates,
929 .add = ec_point_add,
930 .dbl = ec_point_dbl,
931 .invert = ec_point_invert,
932 .point_is_on_curve = ec_point_is_on_curve,
933 .point_cmp = ec_point_cmp,
934 .points_make_affine = ec_points_make_affine,
935 .mul_single_ct = ec_mul_single_ct,
936 .mul_double_nonct = ec_mul_double_nonct,
937};
938
939const EC_METHOD *
940EC_GFp_homogeneous_projective_method(void)
941{
942 return &ec_GFp_homogeneous_projective_method;
943}
diff --git a/src/lib/libcrypto/ec/ecp_methods.c b/src/lib/libcrypto/ec/ecp_methods.c
index ced85ceb1e..fcb48d9e33 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.47 2025/05/24 08:25:58 jsing 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;
@@ -1281,6 +1296,8 @@ ec_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
1281static const EC_METHOD ec_GFp_simple_method = { 1296static const EC_METHOD ec_GFp_simple_method = {
1282 .group_set_curve = ec_group_set_curve, 1297 .group_set_curve = ec_group_set_curve,
1283 .group_get_curve = ec_group_get_curve, 1298 .group_get_curve = ec_group_get_curve,
1299 .point_set_to_infinity = ec_point_set_to_infinity,
1300 .point_is_at_infinity = ec_point_is_at_infinity,
1284 .point_is_on_curve = ec_point_is_on_curve, 1301 .point_is_on_curve = ec_point_is_on_curve,
1285 .point_cmp = ec_point_cmp, 1302 .point_cmp = ec_point_cmp,
1286 .point_set_affine_coordinates = ec_point_set_affine_coordinates, 1303 .point_set_affine_coordinates = ec_point_set_affine_coordinates,
@@ -1304,6 +1321,8 @@ EC_GFp_simple_method(void)
1304static const EC_METHOD ec_GFp_mont_method = { 1321static const EC_METHOD ec_GFp_mont_method = {
1305 .group_set_curve = ec_mont_group_set_curve, 1322 .group_set_curve = ec_mont_group_set_curve,
1306 .group_get_curve = ec_group_get_curve, 1323 .group_get_curve = ec_group_get_curve,
1324 .point_set_to_infinity = ec_point_set_to_infinity,
1325 .point_is_at_infinity = ec_point_is_at_infinity,
1307 .point_is_on_curve = ec_point_is_on_curve, 1326 .point_is_on_curve = ec_point_is_on_curve,
1308 .point_cmp = ec_point_cmp, 1327 .point_cmp = ec_point_cmp,
1309 .point_set_affine_coordinates = ec_point_set_affine_coordinates, 1328 .point_set_affine_coordinates = ec_point_set_affine_coordinates,
diff --git a/src/lib/libcrypto/ec/ecx_methods.c b/src/lib/libcrypto/ec/ecx_methods.c
index 6b5759d4fa..b08456d03b 100644
--- a/src/lib/libcrypto/ec/ecx_methods.c
+++ b/src/lib/libcrypto/ec/ecx_methods.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ecx_methods.c,v 1.14 2024/08/28 07:15:04 tb Exp $ */ 1/* $OpenBSD: ecx_methods.c,v 1.15 2025/05/10 05:54:38 tb Exp $ */
2/* 2/*
3 * Copyright (c) 2022 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2022 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -20,13 +20,13 @@
20#include <openssl/cms.h> 20#include <openssl/cms.h>
21#include <openssl/curve25519.h> 21#include <openssl/curve25519.h>
22#include <openssl/ec.h> 22#include <openssl/ec.h>
23#include <openssl/err.h>
24#include <openssl/evp.h> 23#include <openssl/evp.h>
25#include <openssl/x509.h> 24#include <openssl/x509.h>
26 25
27#include "asn1_local.h" 26#include "asn1_local.h"
28#include "bytestring.h" 27#include "bytestring.h"
29#include "curve25519_internal.h" 28#include "curve25519_internal.h"
29#include "err_local.h"
30#include "evp_local.h" 30#include "evp_local.h"
31#include "x509_local.h" 31#include "x509_local.h"
32 32