xref: /aosp_15_r20/external/boringssl/src/crypto/fipsmodule/ec/ec.c (revision 8fb009dc861624b67b6cdb62ea21f0f22d0c584b)
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