1 /* Originally written by Bodo Moeller for the OpenSSL project.
2 * ====================================================================
3 * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 *
17 * 3. All advertising materials mentioning features or use of this
18 * software must display the following acknowledgment:
19 * "This product includes software developed by the OpenSSL Project
20 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
21 *
22 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23 * endorse or promote products derived from this software without
24 * prior written permission. For written permission, please contact
25 * [email protected].
26 *
27 * 5. Products derived from this software may not be called "OpenSSL"
28 * nor may "OpenSSL" appear in their names without prior written
29 * permission of the OpenSSL Project.
30 *
31 * 6. Redistributions of any form whatsoever must retain the following
32 * acknowledgment:
33 * "This product includes software developed by the OpenSSL Project
34 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
35 *
36 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47 * OF THE POSSIBILITY OF SUCH DAMAGE.
48 * ====================================================================
49 *
50 * This product includes cryptographic software written by Eric Young
51 * ([email protected]). This product includes software written by Tim
52 * Hudson ([email protected]).
53 *
54 */
55 /* ====================================================================
56 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
57 *
58 * Portions of the attached software ("Contribution") are developed by
59 * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
60 *
61 * The Contribution is licensed pursuant to the OpenSSL open source
62 * license provided above.
63 *
64 * The elliptic curve binary polynomial software is originally written by
65 * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems
66 * Laboratories. */
67
68 #include <openssl/ec.h>
69
70 #include <assert.h>
71 #include <string.h>
72
73 #include <openssl/bn.h>
74 #include <openssl/err.h>
75 #include <openssl/mem.h>
76 #include <openssl/nid.h>
77
78 #include "internal.h"
79 #include "../../internal.h"
80 #include "../bn/internal.h"
81 #include "../delocate.h"
82
83 #include "builtin_curves.h"
84
85
86 static void ec_point_free(EC_POINT *point, int free_group);
87
ec_group_init_static_mont(BN_MONT_CTX * mont,size_t num_words,const BN_ULONG * modulus,const BN_ULONG * rr,uint64_t n0)88 static void ec_group_init_static_mont(BN_MONT_CTX *mont, size_t num_words,
89 const BN_ULONG *modulus,
90 const BN_ULONG *rr, uint64_t n0) {
91 bn_set_static_words(&mont->N, modulus, num_words);
92 bn_set_static_words(&mont->RR, rr, num_words);
93 #if defined(OPENSSL_64_BIT)
94 mont->n0[0] = n0;
95 #elif defined(OPENSSL_32_BIT)
96 mont->n0[0] = (uint32_t)n0;
97 mont->n0[1] = (uint32_t)(n0 >> 32);
98 #else
99 #error "unknown word length"
100 #endif
101 }
102
ec_group_set_a_minus3(EC_GROUP * group)103 static void ec_group_set_a_minus3(EC_GROUP *group) {
104 const EC_FELEM *one = ec_felem_one(group);
105 group->a_is_minus3 = 1;
106 ec_felem_neg(group, &group->a, one);
107 ec_felem_sub(group, &group->a, &group->a, one);
108 ec_felem_sub(group, &group->a, &group->a, one);
109 }
110
DEFINE_METHOD_FUNCTION(EC_GROUP,EC_group_p224)111 DEFINE_METHOD_FUNCTION(EC_GROUP, EC_group_p224) {
112 out->curve_name = NID_secp224r1;
113 out->comment = "NIST P-224";
114 // 1.3.132.0.33
115 static const uint8_t kOIDP224[] = {0x2b, 0x81, 0x04, 0x00, 0x21};
116 OPENSSL_memcpy(out->oid, kOIDP224, sizeof(kOIDP224));
117 out->oid_len = sizeof(kOIDP224);
118
119 ec_group_init_static_mont(&out->field, OPENSSL_ARRAY_SIZE(kP224Field),
120 kP224Field, kP224FieldRR, kP224FieldN0);
121 ec_group_init_static_mont(&out->order, OPENSSL_ARRAY_SIZE(kP224Order),
122 kP224Order, kP224OrderRR, kP224OrderN0);
123
124 #if defined(BORINGSSL_HAS_UINT128) && !defined(OPENSSL_SMALL)
125 out->meth = EC_GFp_nistp224_method();
126 OPENSSL_memcpy(out->generator.raw.X.words, kP224GX, sizeof(kP224GX));
127 OPENSSL_memcpy(out->generator.raw.Y.words, kP224GY, sizeof(kP224GY));
128 out->generator.raw.Z.words[0] = 1;
129 OPENSSL_memcpy(out->b.words, kP224B, sizeof(kP224B));
130 #else
131 out->meth = EC_GFp_mont_method();
132 OPENSSL_memcpy(out->generator.raw.X.words, kP224MontGX, sizeof(kP224MontGX));
133 OPENSSL_memcpy(out->generator.raw.Y.words, kP224MontGY, sizeof(kP224MontGY));
134 OPENSSL_memcpy(out->generator.raw.Z.words, kP224FieldR, sizeof(kP224FieldR));
135 OPENSSL_memcpy(out->b.words, kP224MontB, sizeof(kP224MontB));
136 #endif
137 out->generator.group = out;
138
139 ec_group_set_a_minus3(out);
140 out->has_order = 1;
141 out->field_greater_than_order = 1;
142 }
143
DEFINE_METHOD_FUNCTION(EC_GROUP,EC_group_p256)144 DEFINE_METHOD_FUNCTION(EC_GROUP, EC_group_p256) {
145 out->curve_name = NID_X9_62_prime256v1;
146 out->comment = "NIST P-256";
147 // 1.2.840.10045.3.1.7
148 static const uint8_t kOIDP256[] = {0x2a, 0x86, 0x48, 0xce,
149 0x3d, 0x03, 0x01, 0x07};
150 OPENSSL_memcpy(out->oid, kOIDP256, sizeof(kOIDP256));
151 out->oid_len = sizeof(kOIDP256);
152
153 ec_group_init_static_mont(&out->field, OPENSSL_ARRAY_SIZE(kP256Field),
154 kP256Field, kP256FieldRR, kP256FieldN0);
155 ec_group_init_static_mont(&out->order, OPENSSL_ARRAY_SIZE(kP256Order),
156 kP256Order, kP256OrderRR, kP256OrderN0);
157
158 #if !defined(OPENSSL_NO_ASM) && \
159 (defined(OPENSSL_X86_64) || defined(OPENSSL_AARCH64)) && \
160 !defined(OPENSSL_SMALL)
161 out->meth = EC_GFp_nistz256_method();
162 #else
163 out->meth = EC_GFp_nistp256_method();
164 #endif
165 out->generator.group = out;
166 OPENSSL_memcpy(out->generator.raw.X.words, kP256MontGX, sizeof(kP256MontGX));
167 OPENSSL_memcpy(out->generator.raw.Y.words, kP256MontGY, sizeof(kP256MontGY));
168 OPENSSL_memcpy(out->generator.raw.Z.words, kP256FieldR, sizeof(kP256FieldR));
169 OPENSSL_memcpy(out->b.words, kP256MontB, sizeof(kP256MontB));
170
171 ec_group_set_a_minus3(out);
172 out->has_order = 1;
173 out->field_greater_than_order = 1;
174 }
175
DEFINE_METHOD_FUNCTION(EC_GROUP,EC_group_p384)176 DEFINE_METHOD_FUNCTION(EC_GROUP, EC_group_p384) {
177 out->curve_name = NID_secp384r1;
178 out->comment = "NIST P-384";
179 // 1.3.132.0.34
180 static const uint8_t kOIDP384[] = {0x2b, 0x81, 0x04, 0x00, 0x22};
181 OPENSSL_memcpy(out->oid, kOIDP384, sizeof(kOIDP384));
182 out->oid_len = sizeof(kOIDP384);
183
184 ec_group_init_static_mont(&out->field, OPENSSL_ARRAY_SIZE(kP384Field),
185 kP384Field, kP384FieldRR, kP384FieldN0);
186 ec_group_init_static_mont(&out->order, OPENSSL_ARRAY_SIZE(kP384Order),
187 kP384Order, kP384OrderRR, kP384OrderN0);
188
189 out->meth = EC_GFp_mont_method();
190 out->generator.group = out;
191 OPENSSL_memcpy(out->generator.raw.X.words, kP384MontGX, sizeof(kP384MontGX));
192 OPENSSL_memcpy(out->generator.raw.Y.words, kP384MontGY, sizeof(kP384MontGY));
193 OPENSSL_memcpy(out->generator.raw.Z.words, kP384FieldR, sizeof(kP384FieldR));
194 OPENSSL_memcpy(out->b.words, kP384MontB, sizeof(kP384MontB));
195
196 ec_group_set_a_minus3(out);
197 out->has_order = 1;
198 out->field_greater_than_order = 1;
199 }
200
DEFINE_METHOD_FUNCTION(EC_GROUP,EC_group_p521)201 DEFINE_METHOD_FUNCTION(EC_GROUP, EC_group_p521) {
202 out->curve_name = NID_secp521r1;
203 out->comment = "NIST P-521";
204 // 1.3.132.0.35
205 static const uint8_t kOIDP521[] = {0x2b, 0x81, 0x04, 0x00, 0x23};
206 OPENSSL_memcpy(out->oid, kOIDP521, sizeof(kOIDP521));
207 out->oid_len = sizeof(kOIDP521);
208
209 ec_group_init_static_mont(&out->field, OPENSSL_ARRAY_SIZE(kP521Field),
210 kP521Field, kP521FieldRR, kP521FieldN0);
211 ec_group_init_static_mont(&out->order, OPENSSL_ARRAY_SIZE(kP521Order),
212 kP521Order, kP521OrderRR, kP521OrderN0);
213
214 out->meth = EC_GFp_mont_method();
215 out->generator.group = out;
216 OPENSSL_memcpy(out->generator.raw.X.words, kP521MontGX, sizeof(kP521MontGX));
217 OPENSSL_memcpy(out->generator.raw.Y.words, kP521MontGY, sizeof(kP521MontGY));
218 OPENSSL_memcpy(out->generator.raw.Z.words, kP521FieldR, sizeof(kP521FieldR));
219 OPENSSL_memcpy(out->b.words, kP521MontB, sizeof(kP521MontB));
220
221 ec_group_set_a_minus3(out);
222 out->has_order = 1;
223 out->field_greater_than_order = 1;
224 }
225
EC_GROUP_new_curve_GFp(const BIGNUM * p,const BIGNUM * a,const BIGNUM * b,BN_CTX * ctx)226 EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
227 const BIGNUM *b, BN_CTX *ctx) {
228 if (BN_num_bytes(p) > EC_MAX_BYTES) {
229 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FIELD);
230 return NULL;
231 }
232
233 BN_CTX *new_ctx = NULL;
234 if (ctx == NULL) {
235 ctx = new_ctx = BN_CTX_new();
236 if (ctx == NULL) {
237 return NULL;
238 }
239 }
240
241 // Historically, |a| and |b| were not required to be fully reduced.
242 // TODO(davidben): Can this be removed?
243 EC_GROUP *ret = NULL;
244 BN_CTX_start(ctx);
245 BIGNUM *a_reduced = BN_CTX_get(ctx);
246 BIGNUM *b_reduced = BN_CTX_get(ctx);
247 if (a_reduced == NULL || b_reduced == NULL ||
248 !BN_nnmod(a_reduced, a, p, ctx) ||
249 !BN_nnmod(b_reduced, b, p, ctx)) {
250 goto err;
251 }
252
253 ret = OPENSSL_zalloc(sizeof(EC_GROUP));
254 if (ret == NULL) {
255 return NULL;
256 }
257 ret->references = 1;
258 ret->meth = EC_GFp_mont_method();
259 bn_mont_ctx_init(&ret->field);
260 bn_mont_ctx_init(&ret->order);
261 ret->generator.group = ret;
262 if (!ec_GFp_simple_group_set_curve(ret, p, a_reduced, b_reduced, ctx)) {
263 EC_GROUP_free(ret);
264 ret = NULL;
265 goto err;
266 }
267
268 err:
269 BN_CTX_end(ctx);
270 BN_CTX_free(new_ctx);
271 return ret;
272 }
273
EC_GROUP_set_generator(EC_GROUP * group,const EC_POINT * generator,const BIGNUM * order,const BIGNUM * cofactor)274 int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
275 const BIGNUM *order, const BIGNUM *cofactor) {
276 if (group->curve_name != NID_undef || group->has_order ||
277 generator->group != group) {
278 // |EC_GROUP_set_generator| may only be used with |EC_GROUP|s returned by
279 // |EC_GROUP_new_curve_GFp| and may only used once on each group.
280 // |generator| must have been created from |EC_GROUP_new_curve_GFp|, not a
281 // copy, so that |generator->group->generator| is set correctly.
282 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
283 return 0;
284 }
285
286 if (BN_num_bytes(order) > EC_MAX_BYTES) {
287 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_GROUP_ORDER);
288 return 0;
289 }
290
291 // Require a cofactor of one for custom curves, which implies prime order.
292 if (!BN_is_one(cofactor)) {
293 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COFACTOR);
294 return 0;
295 }
296
297 // Require that p < 2×order. This simplifies some ECDSA operations.
298 //
299 // Note any curve which did not satisfy this must have been invalid or use a
300 // tiny prime (less than 17). See the proof in |field_element_to_scalar| in
301 // the ECDSA implementation.
302 int ret = 0;
303 BIGNUM *tmp = BN_new();
304 if (tmp == NULL ||
305 !BN_lshift1(tmp, order)) {
306 goto err;
307 }
308 if (BN_cmp(tmp, &group->field.N) <= 0) {
309 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_GROUP_ORDER);
310 goto err;
311 }
312
313 EC_AFFINE affine;
314 if (!ec_jacobian_to_affine(group, &affine, &generator->raw) ||
315 !BN_MONT_CTX_set(&group->order, order, NULL)) {
316 goto err;
317 }
318
319 group->field_greater_than_order = BN_cmp(&group->field.N, order) > 0;
320 group->generator.raw.X = affine.X;
321 group->generator.raw.Y = affine.Y;
322 // |raw.Z| was set to 1 by |EC_GROUP_new_curve_GFp|.
323 group->has_order = 1;
324 ret = 1;
325
326 err:
327 BN_free(tmp);
328 return ret;
329 }
330
EC_GROUP_new_by_curve_name(int nid)331 EC_GROUP *EC_GROUP_new_by_curve_name(int nid) {
332 switch (nid) {
333 case NID_secp224r1:
334 return (EC_GROUP *)EC_group_p224();
335 case NID_X9_62_prime256v1:
336 return (EC_GROUP *)EC_group_p256();
337 case NID_secp384r1:
338 return (EC_GROUP *)EC_group_p384();
339 case NID_secp521r1:
340 return (EC_GROUP *)EC_group_p521();
341 default:
342 OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
343 return NULL;
344 }
345 }
346
EC_GROUP_free(EC_GROUP * group)347 void EC_GROUP_free(EC_GROUP *group) {
348 if (group == NULL ||
349 // Built-in curves are static.
350 group->curve_name != NID_undef ||
351 !CRYPTO_refcount_dec_and_test_zero(&group->references)) {
352 return;
353 }
354
355 bn_mont_ctx_cleanup(&group->order);
356 bn_mont_ctx_cleanup(&group->field);
357 OPENSSL_free(group);
358 }
359
EC_GROUP_dup(const EC_GROUP * a)360 EC_GROUP *EC_GROUP_dup(const EC_GROUP *a) {
361 if (a == NULL ||
362 // Built-in curves are static.
363 a->curve_name != NID_undef) {
364 return (EC_GROUP *)a;
365 }
366
367 // Groups are logically immutable (but for |EC_GROUP_set_generator| which must
368 // be called early on), so we simply take a reference.
369 EC_GROUP *group = (EC_GROUP *)a;
370 CRYPTO_refcount_inc(&group->references);
371 return group;
372 }
373
EC_GROUP_cmp(const EC_GROUP * a,const EC_GROUP * b,BN_CTX * ignored)374 int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ignored) {
375 // Note this function returns 0 if equal and non-zero otherwise.
376 if (a == b) {
377 return 0;
378 }
379 if (a->curve_name != b->curve_name) {
380 return 1;
381 }
382 if (a->curve_name != NID_undef) {
383 // Built-in curves may be compared by curve name alone.
384 return 0;
385 }
386
387 // |a| and |b| are both custom curves. We compare the entire curve
388 // structure. If |a| or |b| is incomplete (due to legacy OpenSSL mistakes,
389 // custom curve construction is sadly done in two parts) but otherwise not the
390 // same object, we consider them always unequal.
391 return a->meth != b->meth || //
392 !a->has_order || !b->has_order ||
393 BN_cmp(&a->order.N, &b->order.N) != 0 ||
394 BN_cmp(&a->field.N, &b->field.N) != 0 ||
395 !ec_felem_equal(a, &a->a, &b->a) || //
396 !ec_felem_equal(a, &a->b, &b->b) ||
397 !ec_GFp_simple_points_equal(a, &a->generator.raw, &b->generator.raw);
398 }
399
EC_GROUP_get0_generator(const EC_GROUP * group)400 const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) {
401 return group->has_order ? &group->generator : NULL;
402 }
403
EC_GROUP_get0_order(const EC_GROUP * group)404 const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group) {
405 assert(group->has_order);
406 return &group->order.N;
407 }
408
EC_GROUP_get_order(const EC_GROUP * group,BIGNUM * order,BN_CTX * ctx)409 int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) {
410 if (BN_copy(order, EC_GROUP_get0_order(group)) == NULL) {
411 return 0;
412 }
413 return 1;
414 }
415
EC_GROUP_order_bits(const EC_GROUP * group)416 int EC_GROUP_order_bits(const EC_GROUP *group) {
417 return BN_num_bits(&group->order.N);
418 }
419
EC_GROUP_get_cofactor(const EC_GROUP * group,BIGNUM * cofactor,BN_CTX * ctx)420 int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
421 BN_CTX *ctx) {
422 // All |EC_GROUP|s have cofactor 1.
423 return BN_set_word(cofactor, 1);
424 }
425
EC_GROUP_get_curve_GFp(const EC_GROUP * group,BIGNUM * out_p,BIGNUM * out_a,BIGNUM * out_b,BN_CTX * ctx)426 int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *out_p, BIGNUM *out_a,
427 BIGNUM *out_b, BN_CTX *ctx) {
428 return ec_GFp_simple_group_get_curve(group, out_p, out_a, out_b);
429 }
430
EC_GROUP_get_curve_name(const EC_GROUP * group)431 int EC_GROUP_get_curve_name(const EC_GROUP *group) { return group->curve_name; }
432
EC_GROUP_get_degree(const EC_GROUP * group)433 unsigned EC_GROUP_get_degree(const EC_GROUP *group) {
434 return BN_num_bits(&group->field.N);
435 }
436
EC_curve_nid2nist(int nid)437 const char *EC_curve_nid2nist(int nid) {
438 switch (nid) {
439 case NID_secp224r1:
440 return "P-224";
441 case NID_X9_62_prime256v1:
442 return "P-256";
443 case NID_secp384r1:
444 return "P-384";
445 case NID_secp521r1:
446 return "P-521";
447 }
448 return NULL;
449 }
450
EC_curve_nist2nid(const char * name)451 int EC_curve_nist2nid(const char *name) {
452 if (strcmp(name, "P-224") == 0) {
453 return NID_secp224r1;
454 }
455 if (strcmp(name, "P-256") == 0) {
456 return NID_X9_62_prime256v1;
457 }
458 if (strcmp(name, "P-384") == 0) {
459 return NID_secp384r1;
460 }
461 if (strcmp(name, "P-521") == 0) {
462 return NID_secp521r1;
463 }
464 return NID_undef;
465 }
466
EC_POINT_new(const EC_GROUP * group)467 EC_POINT *EC_POINT_new(const EC_GROUP *group) {
468 if (group == NULL) {
469 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
470 return NULL;
471 }
472
473 EC_POINT *ret = OPENSSL_malloc(sizeof *ret);
474 if (ret == NULL) {
475 return NULL;
476 }
477
478 ret->group = EC_GROUP_dup(group);
479 ec_GFp_simple_point_init(&ret->raw);
480 return ret;
481 }
482
ec_point_free(EC_POINT * point,int free_group)483 static void ec_point_free(EC_POINT *point, int free_group) {
484 if (!point) {
485 return;
486 }
487 if (free_group) {
488 EC_GROUP_free(point->group);
489 }
490 OPENSSL_free(point);
491 }
492
EC_POINT_free(EC_POINT * point)493 void EC_POINT_free(EC_POINT *point) {
494 ec_point_free(point, 1 /* free group */);
495 }
496
EC_POINT_clear_free(EC_POINT * point)497 void EC_POINT_clear_free(EC_POINT *point) { EC_POINT_free(point); }
498
EC_POINT_copy(EC_POINT * dest,const EC_POINT * src)499 int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) {
500 if (EC_GROUP_cmp(dest->group, src->group, NULL) != 0) {
501 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
502 return 0;
503 }
504 if (dest == src) {
505 return 1;
506 }
507 ec_GFp_simple_point_copy(&dest->raw, &src->raw);
508 return 1;
509 }
510
EC_POINT_dup(const EC_POINT * a,const EC_GROUP * group)511 EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) {
512 if (a == NULL) {
513 return NULL;
514 }
515
516 EC_POINT *ret = EC_POINT_new(group);
517 if (ret == NULL ||
518 !EC_POINT_copy(ret, a)) {
519 EC_POINT_free(ret);
520 return NULL;
521 }
522
523 return ret;
524 }
525
EC_POINT_set_to_infinity(const EC_GROUP * group,EC_POINT * point)526 int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) {
527 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
528 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
529 return 0;
530 }
531 ec_GFp_simple_point_set_to_infinity(group, &point->raw);
532 return 1;
533 }
534
EC_POINT_is_at_infinity(const EC_GROUP * group,const EC_POINT * point)535 int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) {
536 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
537 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
538 return 0;
539 }
540 return ec_GFp_simple_is_at_infinity(group, &point->raw);
541 }
542
EC_POINT_is_on_curve(const EC_GROUP * group,const EC_POINT * point,BN_CTX * ctx)543 int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
544 BN_CTX *ctx) {
545 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
546 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
547 return 0;
548 }
549 return ec_GFp_simple_is_on_curve(group, &point->raw);
550 }
551
EC_POINT_cmp(const EC_GROUP * group,const EC_POINT * a,const EC_POINT * b,BN_CTX * ctx)552 int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
553 BN_CTX *ctx) {
554 if (EC_GROUP_cmp(group, a->group, NULL) != 0 ||
555 EC_GROUP_cmp(group, b->group, NULL) != 0) {
556 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
557 return -1;
558 }
559
560 // Note |EC_POINT_cmp| returns zero for equality and non-zero for inequality.
561 return ec_GFp_simple_points_equal(group, &a->raw, &b->raw) ? 0 : 1;
562 }
563
EC_POINT_get_affine_coordinates_GFp(const EC_GROUP * group,const EC_POINT * point,BIGNUM * x,BIGNUM * y,BN_CTX * ctx)564 int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
565 const EC_POINT *point, BIGNUM *x,
566 BIGNUM *y, BN_CTX *ctx) {
567 if (group->meth->point_get_affine_coordinates == 0) {
568 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
569 return 0;
570 }
571 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
572 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
573 return 0;
574 }
575 EC_FELEM x_felem, y_felem;
576 if (!group->meth->point_get_affine_coordinates(group, &point->raw,
577 x == NULL ? NULL : &x_felem,
578 y == NULL ? NULL : &y_felem) ||
579 (x != NULL && !ec_felem_to_bignum(group, x, &x_felem)) ||
580 (y != NULL && !ec_felem_to_bignum(group, y, &y_felem))) {
581 return 0;
582 }
583 return 1;
584 }
585
EC_POINT_get_affine_coordinates(const EC_GROUP * group,const EC_POINT * point,BIGNUM * x,BIGNUM * y,BN_CTX * ctx)586 int EC_POINT_get_affine_coordinates(const EC_GROUP *group,
587 const EC_POINT *point, BIGNUM *x, BIGNUM *y,
588 BN_CTX *ctx) {
589 return EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx);
590 }
591
ec_affine_to_jacobian(const EC_GROUP * group,EC_JACOBIAN * out,const EC_AFFINE * p)592 void ec_affine_to_jacobian(const EC_GROUP *group, EC_JACOBIAN *out,
593 const EC_AFFINE *p) {
594 out->X = p->X;
595 out->Y = p->Y;
596 out->Z = *ec_felem_one(group);
597 }
598
ec_jacobian_to_affine(const EC_GROUP * group,EC_AFFINE * out,const EC_JACOBIAN * p)599 int ec_jacobian_to_affine(const EC_GROUP *group, EC_AFFINE *out,
600 const EC_JACOBIAN *p) {
601 return group->meth->point_get_affine_coordinates(group, p, &out->X, &out->Y);
602 }
603
ec_jacobian_to_affine_batch(const EC_GROUP * group,EC_AFFINE * out,const EC_JACOBIAN * in,size_t num)604 int ec_jacobian_to_affine_batch(const EC_GROUP *group, EC_AFFINE *out,
605 const EC_JACOBIAN *in, size_t num) {
606 if (group->meth->jacobian_to_affine_batch == NULL) {
607 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
608 return 0;
609 }
610 return group->meth->jacobian_to_affine_batch(group, out, in, num);
611 }
612
ec_point_set_affine_coordinates(const EC_GROUP * group,EC_AFFINE * out,const EC_FELEM * x,const EC_FELEM * y)613 int ec_point_set_affine_coordinates(const EC_GROUP *group, EC_AFFINE *out,
614 const EC_FELEM *x, const EC_FELEM *y) {
615 void (*const felem_mul)(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a,
616 const EC_FELEM *b) = group->meth->felem_mul;
617 void (*const felem_sqr)(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a) =
618 group->meth->felem_sqr;
619
620 // Check if the point is on the curve.
621 EC_FELEM lhs, rhs;
622 felem_sqr(group, &lhs, y); // lhs = y^2
623 felem_sqr(group, &rhs, x); // rhs = x^2
624 ec_felem_add(group, &rhs, &rhs, &group->a); // rhs = x^2 + a
625 felem_mul(group, &rhs, &rhs, x); // rhs = x^3 + ax
626 ec_felem_add(group, &rhs, &rhs, &group->b); // rhs = x^3 + ax + b
627 if (!ec_felem_equal(group, &lhs, &rhs)) {
628 OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE);
629 // In the event of an error, defend against the caller not checking the
630 // return value by setting a known safe value. Note this may not be possible
631 // if the caller is in the process of constructing an arbitrary group and
632 // the generator is missing.
633 if (group->has_order) {
634 out->X = group->generator.raw.X;
635 out->Y = group->generator.raw.Y;
636 }
637 return 0;
638 }
639
640 out->X = *x;
641 out->Y = *y;
642 return 1;
643 }
644
EC_POINT_set_affine_coordinates_GFp(const EC_GROUP * group,EC_POINT * point,const BIGNUM * x,const BIGNUM * y,BN_CTX * ctx)645 int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
646 const BIGNUM *x, const BIGNUM *y,
647 BN_CTX *ctx) {
648 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
649 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
650 return 0;
651 }
652
653 if (x == NULL || y == NULL) {
654 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
655 return 0;
656 }
657
658 EC_FELEM x_felem, y_felem;
659 EC_AFFINE affine;
660 if (!ec_bignum_to_felem(group, &x_felem, x) ||
661 !ec_bignum_to_felem(group, &y_felem, y) ||
662 !ec_point_set_affine_coordinates(group, &affine, &x_felem, &y_felem)) {
663 // In the event of an error, defend against the caller not checking the
664 // return value by setting a known safe value.
665 ec_set_to_safe_point(group, &point->raw);
666 return 0;
667 }
668
669 ec_affine_to_jacobian(group, &point->raw, &affine);
670 return 1;
671 }
672
EC_POINT_set_affine_coordinates(const EC_GROUP * group,EC_POINT * point,const BIGNUM * x,const BIGNUM * y,BN_CTX * ctx)673 int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
674 const BIGNUM *x, const BIGNUM *y,
675 BN_CTX *ctx) {
676 return EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx);
677 }
678
EC_POINT_add(const EC_GROUP * group,EC_POINT * r,const EC_POINT * a,const EC_POINT * b,BN_CTX * ctx)679 int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
680 const EC_POINT *b, BN_CTX *ctx) {
681 if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
682 EC_GROUP_cmp(group, a->group, NULL) != 0 ||
683 EC_GROUP_cmp(group, b->group, NULL) != 0) {
684 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
685 return 0;
686 }
687 group->meth->add(group, &r->raw, &a->raw, &b->raw);
688 return 1;
689 }
690
EC_POINT_dbl(const EC_GROUP * group,EC_POINT * r,const EC_POINT * a,BN_CTX * ctx)691 int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
692 BN_CTX *ctx) {
693 if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
694 EC_GROUP_cmp(group, a->group, NULL) != 0) {
695 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
696 return 0;
697 }
698 group->meth->dbl(group, &r->raw, &a->raw);
699 return 1;
700 }
701
702
EC_POINT_invert(const EC_GROUP * group,EC_POINT * a,BN_CTX * ctx)703 int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) {
704 if (EC_GROUP_cmp(group, a->group, NULL) != 0) {
705 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
706 return 0;
707 }
708 ec_GFp_simple_invert(group, &a->raw);
709 return 1;
710 }
711
arbitrary_bignum_to_scalar(const EC_GROUP * group,EC_SCALAR * out,const BIGNUM * in,BN_CTX * ctx)712 static int arbitrary_bignum_to_scalar(const EC_GROUP *group, EC_SCALAR *out,
713 const BIGNUM *in, BN_CTX *ctx) {
714 if (ec_bignum_to_scalar(group, out, in)) {
715 return 1;
716 }
717
718 ERR_clear_error();
719
720 // This is an unusual input, so we do not guarantee constant-time processing.
721 BN_CTX_start(ctx);
722 BIGNUM *tmp = BN_CTX_get(ctx);
723 int ok = tmp != NULL &&
724 BN_nnmod(tmp, in, EC_GROUP_get0_order(group), ctx) &&
725 ec_bignum_to_scalar(group, out, tmp);
726 BN_CTX_end(ctx);
727 return ok;
728 }
729
ec_point_mul_no_self_test(const EC_GROUP * group,EC_POINT * r,const BIGNUM * g_scalar,const EC_POINT * p,const BIGNUM * p_scalar,BN_CTX * ctx)730 int ec_point_mul_no_self_test(const EC_GROUP *group, EC_POINT *r,
731 const BIGNUM *g_scalar, const EC_POINT *p,
732 const BIGNUM *p_scalar, BN_CTX *ctx) {
733 // Previously, this function set |r| to the point at infinity if there was
734 // nothing to multiply. But, nobody should be calling this function with
735 // nothing to multiply in the first place.
736 if ((g_scalar == NULL && p_scalar == NULL) ||
737 (p == NULL) != (p_scalar == NULL)) {
738 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
739 return 0;
740 }
741
742 if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
743 (p != NULL && EC_GROUP_cmp(group, p->group, NULL) != 0)) {
744 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
745 return 0;
746 }
747
748 int ret = 0;
749 BN_CTX *new_ctx = NULL;
750 if (ctx == NULL) {
751 new_ctx = BN_CTX_new();
752 if (new_ctx == NULL) {
753 goto err;
754 }
755 ctx = new_ctx;
756 }
757
758 // If both |g_scalar| and |p_scalar| are non-NULL,
759 // |ec_point_mul_scalar_public| would share the doublings between the two
760 // products, which would be more efficient. However, we conservatively assume
761 // the caller needs a constant-time operation. (ECDSA verification does not
762 // use this function.)
763 //
764 // Previously, the low-level constant-time multiplication function aligned
765 // with this function's calling convention, but this was misleading. Curves
766 // which combined the two multiplications did not avoid the doubling case
767 // in the incomplete addition formula and were not constant-time.
768
769 if (g_scalar != NULL) {
770 EC_SCALAR scalar;
771 if (!arbitrary_bignum_to_scalar(group, &scalar, g_scalar, ctx) ||
772 !ec_point_mul_scalar_base(group, &r->raw, &scalar)) {
773 goto err;
774 }
775 }
776
777 if (p_scalar != NULL) {
778 EC_SCALAR scalar;
779 EC_JACOBIAN tmp;
780 if (!arbitrary_bignum_to_scalar(group, &scalar, p_scalar, ctx) ||
781 !ec_point_mul_scalar(group, &tmp, &p->raw, &scalar)) {
782 goto err;
783 }
784 if (g_scalar == NULL) {
785 OPENSSL_memcpy(&r->raw, &tmp, sizeof(EC_JACOBIAN));
786 } else {
787 group->meth->add(group, &r->raw, &r->raw, &tmp);
788 }
789 }
790
791 ret = 1;
792
793 err:
794 BN_CTX_free(new_ctx);
795 return ret;
796 }
797
EC_POINT_mul(const EC_GROUP * group,EC_POINT * r,const BIGNUM * g_scalar,const EC_POINT * p,const BIGNUM * p_scalar,BN_CTX * ctx)798 int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
799 const EC_POINT *p, const BIGNUM *p_scalar, BN_CTX *ctx) {
800 boringssl_ensure_ecc_self_test();
801
802 return ec_point_mul_no_self_test(group, r, g_scalar, p, p_scalar, ctx);
803 }
804
ec_point_mul_scalar_public(const EC_GROUP * group,EC_JACOBIAN * r,const EC_SCALAR * g_scalar,const EC_JACOBIAN * p,const EC_SCALAR * p_scalar)805 int ec_point_mul_scalar_public(const EC_GROUP *group, EC_JACOBIAN *r,
806 const EC_SCALAR *g_scalar, const EC_JACOBIAN *p,
807 const EC_SCALAR *p_scalar) {
808 if (g_scalar == NULL || p_scalar == NULL || p == NULL) {
809 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
810 return 0;
811 }
812
813 if (group->meth->mul_public == NULL) {
814 return group->meth->mul_public_batch(group, r, g_scalar, p, p_scalar, 1);
815 }
816
817 group->meth->mul_public(group, r, g_scalar, p, p_scalar);
818 return 1;
819 }
820
ec_point_mul_scalar_public_batch(const EC_GROUP * group,EC_JACOBIAN * r,const EC_SCALAR * g_scalar,const EC_JACOBIAN * points,const EC_SCALAR * scalars,size_t num)821 int ec_point_mul_scalar_public_batch(const EC_GROUP *group, EC_JACOBIAN *r,
822 const EC_SCALAR *g_scalar,
823 const EC_JACOBIAN *points,
824 const EC_SCALAR *scalars, size_t num) {
825 if (group->meth->mul_public_batch == NULL) {
826 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
827 return 0;
828 }
829
830 return group->meth->mul_public_batch(group, r, g_scalar, points, scalars,
831 num);
832 }
833
ec_point_mul_scalar(const EC_GROUP * group,EC_JACOBIAN * r,const EC_JACOBIAN * p,const EC_SCALAR * scalar)834 int ec_point_mul_scalar(const EC_GROUP *group, EC_JACOBIAN *r,
835 const EC_JACOBIAN *p, const EC_SCALAR *scalar) {
836 if (p == NULL || scalar == NULL) {
837 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
838 return 0;
839 }
840
841 group->meth->mul(group, r, p, scalar);
842
843 // Check the result is on the curve to defend against fault attacks or bugs.
844 // This has negligible cost compared to the multiplication.
845 if (!ec_GFp_simple_is_on_curve(group, r)) {
846 OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
847 return 0;
848 }
849
850 return 1;
851 }
852
ec_point_mul_scalar_base(const EC_GROUP * group,EC_JACOBIAN * r,const EC_SCALAR * scalar)853 int ec_point_mul_scalar_base(const EC_GROUP *group, EC_JACOBIAN *r,
854 const EC_SCALAR *scalar) {
855 if (scalar == NULL) {
856 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
857 return 0;
858 }
859
860 group->meth->mul_base(group, r, scalar);
861
862 // Check the result is on the curve to defend against fault attacks or bugs.
863 // This has negligible cost compared to the multiplication. This can only
864 // happen on bug or CPU fault, so it okay to leak this. The alternative would
865 // be to proceed with bad data.
866 if (!constant_time_declassify_int(ec_GFp_simple_is_on_curve(group, r))) {
867 OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
868 return 0;
869 }
870
871 return 1;
872 }
873
ec_point_mul_scalar_batch(const EC_GROUP * group,EC_JACOBIAN * r,const EC_JACOBIAN * p0,const EC_SCALAR * scalar0,const EC_JACOBIAN * p1,const EC_SCALAR * scalar1,const EC_JACOBIAN * p2,const EC_SCALAR * scalar2)874 int ec_point_mul_scalar_batch(const EC_GROUP *group, EC_JACOBIAN *r,
875 const EC_JACOBIAN *p0, const EC_SCALAR *scalar0,
876 const EC_JACOBIAN *p1, const EC_SCALAR *scalar1,
877 const EC_JACOBIAN *p2,
878 const EC_SCALAR *scalar2) {
879 if (group->meth->mul_batch == NULL) {
880 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
881 return 0;
882 }
883
884 group->meth->mul_batch(group, r, p0, scalar0, p1, scalar1, p2, scalar2);
885
886 // Check the result is on the curve to defend against fault attacks or bugs.
887 // This has negligible cost compared to the multiplication.
888 if (!ec_GFp_simple_is_on_curve(group, r)) {
889 OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
890 return 0;
891 }
892
893 return 1;
894 }
895
ec_init_precomp(const EC_GROUP * group,EC_PRECOMP * out,const EC_JACOBIAN * p)896 int ec_init_precomp(const EC_GROUP *group, EC_PRECOMP *out,
897 const EC_JACOBIAN *p) {
898 if (group->meth->init_precomp == NULL) {
899 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
900 return 0;
901 }
902
903 return group->meth->init_precomp(group, out, p);
904 }
905
ec_point_mul_scalar_precomp(const EC_GROUP * group,EC_JACOBIAN * r,const EC_PRECOMP * p0,const EC_SCALAR * scalar0,const EC_PRECOMP * p1,const EC_SCALAR * scalar1,const EC_PRECOMP * p2,const EC_SCALAR * scalar2)906 int ec_point_mul_scalar_precomp(const EC_GROUP *group, EC_JACOBIAN *r,
907 const EC_PRECOMP *p0, const EC_SCALAR *scalar0,
908 const EC_PRECOMP *p1, const EC_SCALAR *scalar1,
909 const EC_PRECOMP *p2,
910 const EC_SCALAR *scalar2) {
911 if (group->meth->mul_precomp == NULL) {
912 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
913 return 0;
914 }
915
916 group->meth->mul_precomp(group, r, p0, scalar0, p1, scalar1, p2, scalar2);
917
918 // Check the result is on the curve to defend against fault attacks or bugs.
919 // This has negligible cost compared to the multiplication.
920 if (!ec_GFp_simple_is_on_curve(group, r)) {
921 OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
922 return 0;
923 }
924
925 return 1;
926 }
927
ec_point_select(const EC_GROUP * group,EC_JACOBIAN * out,BN_ULONG mask,const EC_JACOBIAN * a,const EC_JACOBIAN * b)928 void ec_point_select(const EC_GROUP *group, EC_JACOBIAN *out, BN_ULONG mask,
929 const EC_JACOBIAN *a, const EC_JACOBIAN *b) {
930 ec_felem_select(group, &out->X, mask, &a->X, &b->X);
931 ec_felem_select(group, &out->Y, mask, &a->Y, &b->Y);
932 ec_felem_select(group, &out->Z, mask, &a->Z, &b->Z);
933 }
934
ec_affine_select(const EC_GROUP * group,EC_AFFINE * out,BN_ULONG mask,const EC_AFFINE * a,const EC_AFFINE * b)935 void ec_affine_select(const EC_GROUP *group, EC_AFFINE *out, BN_ULONG mask,
936 const EC_AFFINE *a, const EC_AFFINE *b) {
937 ec_felem_select(group, &out->X, mask, &a->X, &b->X);
938 ec_felem_select(group, &out->Y, mask, &a->Y, &b->Y);
939 }
940
ec_precomp_select(const EC_GROUP * group,EC_PRECOMP * out,BN_ULONG mask,const EC_PRECOMP * a,const EC_PRECOMP * b)941 void ec_precomp_select(const EC_GROUP *group, EC_PRECOMP *out, BN_ULONG mask,
942 const EC_PRECOMP *a, const EC_PRECOMP *b) {
943 static_assert(sizeof(out->comb) == sizeof(*out),
944 "out->comb does not span the entire structure");
945 for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(out->comb); i++) {
946 ec_affine_select(group, &out->comb[i], mask, &a->comb[i], &b->comb[i]);
947 }
948 }
949
ec_cmp_x_coordinate(const EC_GROUP * group,const EC_JACOBIAN * p,const EC_SCALAR * r)950 int ec_cmp_x_coordinate(const EC_GROUP *group, const EC_JACOBIAN *p,
951 const EC_SCALAR *r) {
952 return group->meth->cmp_x_coordinate(group, p, r);
953 }
954
ec_get_x_coordinate_as_scalar(const EC_GROUP * group,EC_SCALAR * out,const EC_JACOBIAN * p)955 int ec_get_x_coordinate_as_scalar(const EC_GROUP *group, EC_SCALAR *out,
956 const EC_JACOBIAN *p) {
957 uint8_t bytes[EC_MAX_BYTES];
958 size_t len;
959 if (!ec_get_x_coordinate_as_bytes(group, bytes, &len, sizeof(bytes), p)) {
960 return 0;
961 }
962
963 // The x-coordinate is bounded by p, but we need a scalar, bounded by the
964 // order. These may not have the same size. However, we must have p < 2×order,
965 // assuming p is not tiny (p >= 17).
966 //
967 // Thus |bytes| will fit in |order.width + 1| words, and we can reduce by
968 // performing at most one subtraction.
969 //
970 // Proof: We only work with prime order curves, so the number of points on
971 // the curve is the order. Thus Hasse's theorem gives:
972 //
973 // |order - (p + 1)| <= 2×sqrt(p)
974 // p + 1 - order <= 2×sqrt(p)
975 // p + 1 - 2×sqrt(p) <= order
976 // p + 1 - 2×(p/4) < order (p/4 > sqrt(p) for p >= 17)
977 // p/2 < p/2 + 1 < order
978 // p < 2×order
979 //
980 // Additionally, one can manually check this property for built-in curves. It
981 // is enforced for legacy custom curves in |EC_GROUP_set_generator|.
982 const BIGNUM *order = EC_GROUP_get0_order(group);
983 BN_ULONG words[EC_MAX_WORDS + 1] = {0};
984 bn_big_endian_to_words(words, order->width + 1, bytes, len);
985 bn_reduce_once(out->words, words, /*carry=*/words[order->width], order->d,
986 order->width);
987 return 1;
988 }
989
ec_get_x_coordinate_as_bytes(const EC_GROUP * group,uint8_t * out,size_t * out_len,size_t max_out,const EC_JACOBIAN * p)990 int ec_get_x_coordinate_as_bytes(const EC_GROUP *group, uint8_t *out,
991 size_t *out_len, size_t max_out,
992 const EC_JACOBIAN *p) {
993 size_t len = BN_num_bytes(&group->field.N);
994 assert(len <= EC_MAX_BYTES);
995 if (max_out < len) {
996 OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL);
997 return 0;
998 }
999
1000 EC_FELEM x;
1001 if (!group->meth->point_get_affine_coordinates(group, p, &x, NULL)) {
1002 return 0;
1003 }
1004
1005 ec_felem_to_bytes(group, out, out_len, &x);
1006 *out_len = len;
1007 return 1;
1008 }
1009
ec_set_to_safe_point(const EC_GROUP * group,EC_JACOBIAN * out)1010 void ec_set_to_safe_point(const EC_GROUP *group, EC_JACOBIAN *out) {
1011 if (group->has_order) {
1012 ec_GFp_simple_point_copy(out, &group->generator.raw);
1013 } else {
1014 // The generator can be missing if the caller is in the process of
1015 // constructing an arbitrary group. In this case, we give up and use the
1016 // point at infinity.
1017 ec_GFp_simple_point_set_to_infinity(group, out);
1018 }
1019 }
1020
EC_GROUP_set_asn1_flag(EC_GROUP * group,int flag)1021 void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) {}
1022
EC_GROUP_get_asn1_flag(const EC_GROUP * group)1023 int EC_GROUP_get_asn1_flag(const EC_GROUP *group) {
1024 return OPENSSL_EC_NAMED_CURVE;
1025 }
1026
EC_GROUP_method_of(const EC_GROUP * group)1027 const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) {
1028 // This function exists purely to give callers a way to call
1029 // |EC_METHOD_get_field_type|. cryptography.io crashes if |EC_GROUP_method_of|
1030 // returns NULL, so return some other garbage pointer.
1031 return (const EC_METHOD *)0x12340000;
1032 }
1033
EC_METHOD_get_field_type(const EC_METHOD * meth)1034 int EC_METHOD_get_field_type(const EC_METHOD *meth) {
1035 return NID_X9_62_prime_field;
1036 }
1037
EC_GROUP_set_point_conversion_form(EC_GROUP * group,point_conversion_form_t form)1038 void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
1039 point_conversion_form_t form) {
1040 if (form != POINT_CONVERSION_UNCOMPRESSED) {
1041 abort();
1042 }
1043 }
1044