summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/ec
diff options
context:
space:
mode:
Diffstat (limited to '')
-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.c4
-rw-r--r--src/lib/libcrypto/ec/ec_curve.c316
-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.c34
-rw-r--r--src/lib/libcrypto/ec/ec_local.h26
-rw-r--r--src/lib/libcrypto/ec/ec_mult.c38
-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.c30
-rw-r--r--src/lib/libcrypto/ec/ecx_methods.c4
-rw-r--r--src/lib/libcrypto/ecdh/ecdh.c4
-rw-r--r--src/lib/libcrypto/ecdsa/ecdsa.c4
17 files changed, 1380 insertions, 310 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..84641a4e72 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.15 2025/05/10 05:54:38 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
diff --git a/src/lib/libcrypto/ec/ec_curve.c b/src/lib/libcrypto/ec/ec_curve.c
index a3ec2de7fb..2cfb219b50 100644
--- a/src/lib/libcrypto/ec/ec_curve.c
+++ b/src/lib/libcrypto/ec/ec_curve.c
@@ -1,4 +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.58 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 */
@@ -78,10 +78,10 @@
78 78
79#include <openssl/bn.h> 79#include <openssl/bn.h>
80#include <openssl/ec.h> 80#include <openssl/ec.h>
81#include <openssl/err.h>
82#include <openssl/objects.h> 81#include <openssl/objects.h>
83 82
84#include "ec_local.h" 83#include "ec_local.h"
84#include "err_local.h"
85 85
86static const struct { 86static const struct {
87 uint8_t seed[20]; 87 uint8_t seed[20];
@@ -130,6 +130,57 @@ static const struct {
130 130
131static const struct { 131static const struct {
132 uint8_t seed[20]; 132 uint8_t seed[20];
133 uint8_t p[32];
134 uint8_t a[32];
135 uint8_t b[32];
136 uint8_t x[32];
137 uint8_t y[32];
138 uint8_t order[32];
139} _EC_NIST_PRIME_256 = {
140 .seed = {
141 0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66,
142 0x78, 0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90,
143 },
144 .p = {
145 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
148 0xff, 0xff,
149 },
150 .a = {
151 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
152 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
154 0xff, 0xfc,
155 },
156 .b = {
157 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb,
158 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0,
159 0xcc, 0x53, 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2,
160 0x60, 0x4b,
161 },
162 .x = {
163 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc,
164 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81,
165 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98,
166 0xc2, 0x96,
167 },
168 .y = {
169 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7,
170 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57,
171 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf,
172 0x51, 0xf5,
173 },
174 .order = {
175 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
176 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad,
177 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63,
178 0x25, 0x51,
179 },
180};
181
182static const struct {
183 uint8_t seed[20];
133 uint8_t p[48]; 184 uint8_t p[48];
134 uint8_t a[48]; 185 uint8_t a[48];
135 uint8_t b[48]; 186 uint8_t b[48];
@@ -255,192 +306,6 @@ static const struct {
255}; 306};
256 307
257static const struct { 308static 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]; 309 uint8_t p[29];
445 uint8_t a[29]; 310 uint8_t a[29];
446 uint8_t b[29]; 311 uint8_t b[29];
@@ -1121,7 +986,21 @@ static const struct ec_curve {
1121 .order = _EC_SECG_PRIME_256K1.order, 986 .order = _EC_SECG_PRIME_256K1.order,
1122 .cofactor = 1, 987 .cofactor = 1,
1123 }, 988 },
1124 /* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */ 989 {
990 /* Everyone except OpenSSL calls this secp256r1 or P-256. */
991 .comment = "X9.62/SECG curve prime256v1",
992 .nid = NID_X9_62_prime256v1,
993 .seed_len = sizeof(_EC_NIST_PRIME_256.seed),
994 .param_len = sizeof(_EC_NIST_PRIME_256.p),
995 .seed = _EC_NIST_PRIME_256.seed,
996 .p = _EC_NIST_PRIME_256.p,
997 .a = _EC_NIST_PRIME_256.a,
998 .b = _EC_NIST_PRIME_256.b,
999 .x = _EC_NIST_PRIME_256.x,
1000 .y = _EC_NIST_PRIME_256.y,
1001 .order = _EC_NIST_PRIME_256.order,
1002 .cofactor = 1,
1003 },
1125 { 1004 {
1126 .comment = "NIST/SECG curve secp384r1", 1005 .comment = "NIST/SECG curve secp384r1",
1127 .nid = NID_secp384r1, 1006 .nid = NID_secp384r1,
@@ -1150,63 +1029,6 @@ static const struct ec_curve {
1150 .order = _EC_NIST_PRIME_521.order, 1029 .order = _EC_NIST_PRIME_521.order,
1151 .cofactor = 1, 1030 .cofactor = 1,
1152 }, 1031 },
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 */ 1032 /* RFC 5639 curves */
1211 { 1033 {
1212 .comment = "RFC 5639 curve brainpoolP224r1", 1034 .comment = "RFC 5639 curve brainpoolP224r1",
@@ -1221,7 +1043,7 @@ static const struct ec_curve {
1221 .cofactor = 1, 1043 .cofactor = 1,
1222 }, 1044 },
1223 { 1045 {
1224 .comment = "RFC 5639 curve brainpoolP224r2", 1046 .comment = "RFC 5639 curve brainpoolP224t1",
1225 .nid = NID_brainpoolP224t1, 1047 .nid = NID_brainpoolP224t1,
1226 .param_len = sizeof(_EC_brainpoolP224t1.p), 1048 .param_len = sizeof(_EC_brainpoolP224t1.p),
1227 .p = _EC_brainpoolP224t1.p, 1049 .p = _EC_brainpoolP224t1.p,
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..327d9ea94d
--- /dev/null
+++ b/src/lib/libcrypto/ec/ec_internal.h
@@ -0,0 +1,65 @@
1/* $OpenBSD: ec_internal.h,v 1.2 2025/08/02 15:44:09 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 <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 + BN_BYTES - 1) / BN_BYTES)
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 315a8130cf..36f42ecc05 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.121 2025/03/09 15:42:19 tb Exp $ */ 1/* $OpenBSD: ec_lib.c,v 1.126 2025/08/02 15:47:27 jsing 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) {
@@ -860,6 +864,10 @@ EC_POINT_copy(EC_POINT *dst, const EC_POINT *src)
860 return 0; 864 return 0;
861 dst->Z_is_one = src->Z_is_one; 865 dst->Z_is_one = src->Z_is_one;
862 866
867 memcpy(&dst->fe_x, &src->fe_x, sizeof(dst->fe_x));
868 memcpy(&dst->fe_y, &src->fe_y, sizeof(dst->fe_y));
869 memcpy(&dst->fe_z, &src->fe_z, sizeof(dst->fe_z));
870
863 return 1; 871 return 1;
864} 872}
865LCRYPTO_ALIAS(EC_POINT_copy); 873LCRYPTO_ALIAS(EC_POINT_copy);
@@ -894,11 +902,7 @@ EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
894 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 902 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
895 return 0; 903 return 0;
896 } 904 }
897 905 return point->meth->point_set_to_infinity(group, point);
898 BN_zero(point->Z);
899 point->Z_is_one = 0;
900
901 return 1;
902} 906}
903LCRYPTO_ALIAS(EC_POINT_set_to_infinity); 907LCRYPTO_ALIAS(EC_POINT_set_to_infinity);
904 908
@@ -1200,8 +1204,7 @@ EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
1200 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 1204 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
1201 return 0; 1205 return 0;
1202 } 1206 }
1203 1207 return point->meth->point_is_at_infinity(group, point);
1204 return BN_is_zero(point->Z);
1205} 1208}
1206LCRYPTO_ALIAS(EC_POINT_is_at_infinity); 1209LCRYPTO_ALIAS(EC_POINT_is_at_infinity);
1207 1210
@@ -1319,6 +1322,11 @@ EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
1319 goto err; 1322 goto err;
1320 } 1323 }
1321 1324
1325 if (g_scalar != NULL && group->generator == NULL) {
1326 ECerror(EC_R_UNDEFINED_GENERATOR);
1327 goto err;
1328 }
1329
1322 if (g_scalar != NULL && point == NULL && p_scalar == NULL) { 1330 if (g_scalar != NULL && point == NULL && p_scalar == NULL) {
1323 /* 1331 /*
1324 * In this case we want to compute g_scalar * GeneratorPoint: 1332 * In this case we want to compute g_scalar * GeneratorPoint:
@@ -1328,8 +1336,8 @@ EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
1328 * secret. This is why we ignore if BN_FLG_CONSTTIME is actually 1336 * secret. This is why we ignore if BN_FLG_CONSTTIME is actually
1329 * set and we always call the constant time version. 1337 * set and we always call the constant time version.
1330 */ 1338 */
1331 ret = group->meth->mul_single_ct(group, r, g_scalar, 1339 ret = group->meth->mul_single_ct(group, r,
1332 group->generator, ctx); 1340 g_scalar, group->generator, ctx);
1333 } else if (g_scalar == NULL && point != NULL && p_scalar != NULL) { 1341 } else if (g_scalar == NULL && point != NULL && p_scalar != NULL) {
1334 /* 1342 /*
1335 * In this case we want to compute p_scalar * GenericPoint: 1343 * In this case we want to compute p_scalar * GenericPoint:
@@ -1347,8 +1355,8 @@ EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
1347 * this codepath is reached most prominently by ECDSA signature 1355 * this codepath is reached most prominently by ECDSA signature
1348 * verification. So we call the non-ct version. 1356 * verification. So we call the non-ct version.
1349 */ 1357 */
1350 ret = group->meth->mul_double_nonct(group, r, g_scalar, 1358 ret = group->meth->mul_double_nonct(group, r,
1351 p_scalar, point, ctx); 1359 g_scalar, group->generator, p_scalar, point, ctx);
1352 } else { 1360 } else {
1353 /* Anything else is an error. */ 1361 /* Anything else is an error. */
1354 ECerror(ERR_R_EC_LIB); 1362 ECerror(ERR_R_EC_LIB);
diff --git a/src/lib/libcrypto/ec/ec_local.h b/src/lib/libcrypto/ec/ec_local.h
index 9c188c0197..eac9e6d26c 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.66 2025/03/09 15:33:35 tb Exp $ */ 1/* $OpenBSD: ec_local.h,v 1.70 2025/08/03 15:07:57 jsing 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 */
@@ -76,6 +76,7 @@
76#include <openssl/objects.h> 76#include <openssl/objects.h>
77 77
78#include "bn_local.h" 78#include "bn_local.h"
79#include "ec_internal.h"
79 80
80__BEGIN_HIDDEN_DECLS 81__BEGIN_HIDDEN_DECLS
81 82
@@ -85,6 +86,9 @@ typedef struct ec_method_st {
85 int (*group_get_curve)(const EC_GROUP *, BIGNUM *p, BIGNUM *a, 86 int (*group_get_curve)(const EC_GROUP *, BIGNUM *p, BIGNUM *a,
86 BIGNUM *b, BN_CTX *); 87 BIGNUM *b, BN_CTX *);
87 88
89 int (*point_set_to_infinity)(const EC_GROUP *, EC_POINT *);
90 int (*point_is_at_infinity)(const EC_GROUP *, const EC_POINT *);
91
88 int (*point_is_on_curve)(const EC_GROUP *, const EC_POINT *, BN_CTX *); 92 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, 93 int (*point_cmp)(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b,
90 BN_CTX *); 94 BN_CTX *);
@@ -106,8 +110,8 @@ typedef struct ec_method_st {
106 int (*mul_single_ct)(const EC_GROUP *group, EC_POINT *r, 110 int (*mul_single_ct)(const EC_GROUP *group, EC_POINT *r,
107 const BIGNUM *scalar, const EC_POINT *point, BN_CTX *); 111 const BIGNUM *scalar, const EC_POINT *point, BN_CTX *);
108 int (*mul_double_nonct)(const EC_GROUP *group, EC_POINT *r, 112 int (*mul_double_nonct)(const EC_GROUP *group, EC_POINT *r,
109 const BIGNUM *g_scalar, const BIGNUM *p_scalar, 113 const BIGNUM *scalar1, const EC_POINT *point1,
110 const EC_POINT *point, BN_CTX *); 114 const BIGNUM *scalar2, const EC_POINT *point2, BN_CTX *);
111 115
112 /* 116 /*
113 * These can be used by 'add' and 'dbl' so that the same implementations 117 * These can be used by 'add' and 'dbl' so that the same implementations
@@ -155,6 +159,10 @@ struct ec_group_st {
155 159
156 /* Montgomery context used by EC_GFp_mont_method. */ 160 /* Montgomery context used by EC_GFp_mont_method. */
157 BN_MONT_CTX *mont_ctx; 161 BN_MONT_CTX *mont_ctx;
162
163 EC_FIELD_MODULUS fm;
164 EC_FIELD_ELEMENT fe_a;
165 EC_FIELD_ELEMENT fe_b;
158} /* EC_GROUP */; 166} /* EC_GROUP */;
159 167
160struct ec_point_st { 168struct ec_point_st {
@@ -168,14 +176,20 @@ struct ec_point_st {
168 BIGNUM *Y; 176 BIGNUM *Y;
169 BIGNUM *Z; 177 BIGNUM *Z;
170 int Z_is_one; /* enable optimized point arithmetics for special case */ 178 int Z_is_one; /* enable optimized point arithmetics for special case */
179
180 EC_FIELD_ELEMENT fe_x;
181 EC_FIELD_ELEMENT fe_y;
182 EC_FIELD_ELEMENT fe_z;
171} /* EC_POINT */; 183} /* EC_POINT */;
172 184
173const EC_METHOD *EC_GFp_simple_method(void); 185const EC_METHOD *EC_GFp_simple_method(void);
174const EC_METHOD *EC_GFp_mont_method(void); 186const EC_METHOD *EC_GFp_mont_method(void);
187const EC_METHOD *EC_GFp_homogeneous_projective_method(void);
175 188
176/* Compute r = generator * m + point * n in non-constant time. */ 189/* Compute r = scalar1 * point1 + scalar2 * point2 in non-constant time. */
177int ec_wnaf_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *m, 190int ec_wnaf_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar1,
178 const EC_POINT *point, const BIGNUM *n, BN_CTX *ctx); 191 const EC_POINT *point1, const BIGNUM *scalar2, const EC_POINT *point2,
192 BN_CTX *ctx);
179 193
180int ec_group_is_builtin_curve(const EC_GROUP *group, int *out_nid); 194int ec_group_is_builtin_curve(const EC_GROUP *group, int *out_nid);
181 195
diff --git a/src/lib/libcrypto/ec/ec_mult.c b/src/lib/libcrypto/ec/ec_mult.c
index 68061ffd67..d74c89cfe2 100644
--- a/src/lib/libcrypto/ec/ec_mult.c
+++ b/src/lib/libcrypto/ec/ec_mult.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec_mult.c,v 1.57 2025/01/11 13:58:31 tb Exp $ */ 1/* $OpenBSD: ec_mult.c,v 1.59 2025/05/10 05:54:38 tb Exp $ */
2/* 2/*
3 * Originally written by Bodo Moeller and Nils Larsch for the OpenSSL project. 3 * Originally written by Bodo Moeller and Nils Larsch for the OpenSSL project.
4 */ 4 */
@@ -67,9 +67,9 @@
67 67
68#include <openssl/bn.h> 68#include <openssl/bn.h>
69#include <openssl/ec.h> 69#include <openssl/ec.h>
70#include <openssl/err.h>
71 70
72#include "ec_local.h" 71#include "ec_local.h"
72#include "err_local.h"
73 73
74/* Holds the wNAF digits of bn and the corresponding odd multiples of point. */ 74/* Holds the wNAF digits of bn and the corresponding odd multiples of point. */
75struct ec_wnaf { 75struct ec_wnaf {
@@ -259,7 +259,7 @@ ec_wnaf_free(struct ec_wnaf *wnaf)
259 */ 259 */
260 260
261static struct ec_wnaf * 261static struct ec_wnaf *
262ec_wnaf_new(const EC_GROUP *group, const EC_POINT *point, const BIGNUM *bn, 262ec_wnaf_new(const EC_GROUP *group, const BIGNUM *scalar, const EC_POINT *point,
263 BN_CTX *ctx) 263 BN_CTX *ctx)
264{ 264{
265 struct ec_wnaf *wnaf; 265 struct ec_wnaf *wnaf;
@@ -267,15 +267,15 @@ ec_wnaf_new(const EC_GROUP *group, const EC_POINT *point, const BIGNUM *bn,
267 if ((wnaf = calloc(1, sizeof(*wnaf))) == NULL) 267 if ((wnaf = calloc(1, sizeof(*wnaf))) == NULL)
268 goto err; 268 goto err;
269 269
270 wnaf->num_digits = BN_num_bits(bn) + 1; 270 wnaf->num_digits = BN_num_bits(scalar) + 1;
271 if ((wnaf->digits = calloc(wnaf->num_digits, 271 if ((wnaf->digits = calloc(wnaf->num_digits,
272 sizeof(*wnaf->digits))) == NULL) 272 sizeof(*wnaf->digits))) == NULL)
273 goto err; 273 goto err;
274 274
275 if (!ec_compute_wnaf(bn, wnaf->digits, wnaf->num_digits)) 275 if (!ec_compute_wnaf(scalar, wnaf->digits, wnaf->num_digits))
276 goto err; 276 goto err;
277 277
278 wnaf->num_multiples = 1ULL << (ec_window_bits(bn) - 1); 278 wnaf->num_multiples = 1ULL << (ec_window_bits(scalar) - 1);
279 if ((wnaf->multiples = calloc(wnaf->num_multiples, 279 if ((wnaf->multiples = calloc(wnaf->num_multiples,
280 sizeof(*wnaf->multiples))) == NULL) 280 sizeof(*wnaf->multiples))) == NULL)
281 goto err; 281 goto err;
@@ -313,38 +313,34 @@ ec_wnaf_multiple(struct ec_wnaf *wnaf, signed char digit)
313} 313}
314 314
315/* 315/*
316 * Compute r = generator * m + point * n in non-constant time. 316 * Compute r = scalar1 * point1 + scalar2 * point2 in non-constant time.
317 */ 317 */
318 318
319int 319int
320ec_wnaf_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *m, 320ec_wnaf_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar1,
321 const EC_POINT *point, const BIGNUM *n, BN_CTX *ctx) 321 const EC_POINT *point1, const BIGNUM *scalar2, const EC_POINT *point2,
322 BN_CTX *ctx)
322{ 323{
323 struct ec_wnaf *wnaf[2] = { NULL, NULL }; 324 struct ec_wnaf *wnaf[2] = { NULL, NULL };
324 const EC_POINT *generator;
325 size_t i; 325 size_t i;
326 int k; 326 int k;
327 int r_is_inverted = 0; 327 int r_is_inverted = 0;
328 size_t num_digits; 328 size_t num_digits;
329 int ret = 0; 329 int ret = 0;
330 330
331 if (m == NULL || n == NULL) { 331 if (scalar1 == NULL || scalar2 == NULL) {
332 ECerror(ERR_R_PASSED_NULL_PARAMETER); 332 ECerror(ERR_R_PASSED_NULL_PARAMETER);
333 goto err; 333 goto err;
334 } 334 }
335 if (group->meth != r->meth || group->meth != point->meth) { 335 if (group->meth != r->meth || group->meth != point1->meth ||
336 group->meth != point2->meth) {
336 ECerror(EC_R_INCOMPATIBLE_OBJECTS); 337 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
337 goto err; 338 goto err;
338 } 339 }
339 340
340 if ((generator = EC_GROUP_get0_generator(group)) == NULL) { 341 if ((wnaf[0] = ec_wnaf_new(group, scalar1, point1, ctx)) == NULL)
341 ECerror(EC_R_UNDEFINED_GENERATOR);
342 goto err;
343 }
344
345 if ((wnaf[0] = ec_wnaf_new(group, generator, m, ctx)) == NULL)
346 goto err; 342 goto err;
347 if ((wnaf[1] = ec_wnaf_new(group, point, n, ctx)) == NULL) 343 if ((wnaf[1] = ec_wnaf_new(group, scalar2, point2, ctx)) == NULL)
348 goto err; 344 goto err;
349 345
350 if (!ec_normalize_points(group, wnaf[0], wnaf[1], ctx)) 346 if (!ec_normalize_points(group, wnaf[0], wnaf[1], ctx))
@@ -357,8 +353,8 @@ ec_wnaf_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *m,
357 /* 353 /*
358 * Set r to the neutral element. Scan through the wNAF representations 354 * Set r to the neutral element. Scan through the wNAF representations
359 * of m and n, starting at the most significant digit. Double r and for 355 * of m and n, starting at the most significant digit. Double r and for
360 * each wNAF digit of m add the digit times the generator, and for each 356 * each wNAF digit of scalar1 add the digit times point1, and for each
361 * wNAF digit of n add the digit times the point, adjusting the signs 357 * wNAF digit of scalar2 add the digit times point2, adjusting the signs
362 * as appropriate. 358 * as appropriate.
363 */ 359 */
364 360
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 544c2be4d4..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.44 2025/03/09 15:33:35 tb 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;
@@ -1194,10 +1209,11 @@ ec_mul_single_ct(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
1194} 1209}
1195 1210
1196static int 1211static int
1197ec_mul_double_nonct(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, 1212ec_mul_double_nonct(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar1,
1198 const BIGNUM *p_scalar, const EC_POINT *point, BN_CTX *ctx) 1213 const EC_POINT *point1, const BIGNUM *scalar2, const EC_POINT *point2,
1214 BN_CTX *ctx)
1199{ 1215{
1200 return ec_wnaf_mul(group, r, g_scalar, point, p_scalar, ctx); 1216 return ec_wnaf_mul(group, r, scalar1, point1, scalar2, point2, ctx);
1201} 1217}
1202 1218
1203static int 1219static int
@@ -1280,6 +1296,8 @@ ec_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
1280static const EC_METHOD ec_GFp_simple_method = { 1296static const EC_METHOD ec_GFp_simple_method = {
1281 .group_set_curve = ec_group_set_curve, 1297 .group_set_curve = ec_group_set_curve,
1282 .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,
1283 .point_is_on_curve = ec_point_is_on_curve, 1301 .point_is_on_curve = ec_point_is_on_curve,
1284 .point_cmp = ec_point_cmp, 1302 .point_cmp = ec_point_cmp,
1285 .point_set_affine_coordinates = ec_point_set_affine_coordinates, 1303 .point_set_affine_coordinates = ec_point_set_affine_coordinates,
@@ -1303,6 +1321,8 @@ EC_GFp_simple_method(void)
1303static const EC_METHOD ec_GFp_mont_method = { 1321static const EC_METHOD ec_GFp_mont_method = {
1304 .group_set_curve = ec_mont_group_set_curve, 1322 .group_set_curve = ec_mont_group_set_curve,
1305 .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,
1306 .point_is_on_curve = ec_point_is_on_curve, 1326 .point_is_on_curve = ec_point_is_on_curve,
1307 .point_cmp = ec_point_cmp, 1327 .point_cmp = ec_point_cmp,
1308 .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
diff --git a/src/lib/libcrypto/ecdh/ecdh.c b/src/lib/libcrypto/ecdh/ecdh.c
index dbb91f1991..c3affed682 100644
--- a/src/lib/libcrypto/ecdh/ecdh.c
+++ b/src/lib/libcrypto/ecdh/ecdh.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ecdh.c,v 1.11 2025/02/17 09:25:45 tb Exp $ */ 1/* $OpenBSD: ecdh.c,v 1.12 2025/05/10 05:54:38 tb Exp $ */
2/* ==================================================================== 2/* ====================================================================
3 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 3 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
4 * 4 *
@@ -73,10 +73,10 @@
73 73
74#include <openssl/bn.h> 74#include <openssl/bn.h>
75#include <openssl/ec.h> 75#include <openssl/ec.h>
76#include <openssl/err.h>
77#include <openssl/evp.h> 76#include <openssl/evp.h>
78 77
79#include "ec_local.h" 78#include "ec_local.h"
79#include "err_local.h"
80 80
81/* 81/*
82 * Key derivation function from X9.63/SECG. 82 * Key derivation function from X9.63/SECG.
diff --git a/src/lib/libcrypto/ecdsa/ecdsa.c b/src/lib/libcrypto/ecdsa/ecdsa.c
index 5abc3586e3..4e00eb5ec8 100644
--- a/src/lib/libcrypto/ecdsa/ecdsa.c
+++ b/src/lib/libcrypto/ecdsa/ecdsa.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ecdsa.c,v 1.19 2024/04/15 15:49:37 tb Exp $ */ 1/* $OpenBSD: ecdsa.c,v 1.20 2025/05/10 05:54:38 tb Exp $ */
2/* ==================================================================== 2/* ====================================================================
3 * Copyright (c) 2000-2002 The OpenSSL Project. All rights reserved. 3 * Copyright (c) 2000-2002 The OpenSSL Project. All rights reserved.
4 * 4 *
@@ -61,11 +61,11 @@
61#include <openssl/asn1t.h> 61#include <openssl/asn1t.h>
62#include <openssl/bn.h> 62#include <openssl/bn.h>
63#include <openssl/ec.h> 63#include <openssl/ec.h>
64#include <openssl/err.h>
65 64
66#include "bn_local.h" 65#include "bn_local.h"
67#include "ec_local.h" 66#include "ec_local.h"
68#include "ecdsa_local.h" 67#include "ecdsa_local.h"
68#include "err_local.h"
69 69
70static const ASN1_TEMPLATE ECDSA_SIG_seq_tt[] = { 70static const ASN1_TEMPLATE ECDSA_SIG_seq_tt[] = {
71 { 71 {