Coverage Report

Created: 2024-11-21 07:03

/src/boringssl/crypto/fipsmodule/ec/ec.c.inc
Line
Count
Source (jump to first uncovered line)
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
 *    openssl-core@openssl.org.
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
 * (eay@cryptsoft.com).  This product includes software written by Tim
52
 * Hudson (tjh@cryptsoft.com).
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
88
static void ec_group_init_static_mont(BN_MONT_CTX *mont, size_t num_words,
89
                                      const BN_ULONG *modulus,
90
16
                                      const BN_ULONG *rr, uint64_t n0) {
91
16
  bn_set_static_words(&mont->N, modulus, num_words);
92
16
  bn_set_static_words(&mont->RR, rr, num_words);
93
16
#if defined(OPENSSL_64_BIT)
94
16
  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
16
}
102
103
8
static void ec_group_set_a_minus3(EC_GROUP *group) {
104
8
  const EC_FELEM *one = ec_felem_one(group);
105
8
  group->a_is_minus3 = 1;
106
8
  ec_felem_neg(group, &group->a, one);
107
8
  ec_felem_sub(group, &group->a, &group->a, one);
108
8
  ec_felem_sub(group, &group->a, &group->a, one);
109
8
}
110
111
2
DEFINE_METHOD_FUNCTION(EC_GROUP, EC_group_p224) {
112
2
  out->curve_name = NID_secp224r1;
113
2
  out->comment = "NIST P-224";
114
  // 1.3.132.0.33
115
2
  static const uint8_t kOIDP224[] = {0x2b, 0x81, 0x04, 0x00, 0x21};
116
2
  OPENSSL_memcpy(out->oid, kOIDP224, sizeof(kOIDP224));
117
2
  out->oid_len = sizeof(kOIDP224);
118
119
2
  ec_group_init_static_mont(&out->field, OPENSSL_ARRAY_SIZE(kP224Field),
120
2
                            kP224Field, kP224FieldRR, kP224FieldN0);
121
2
  ec_group_init_static_mont(&out->order, OPENSSL_ARRAY_SIZE(kP224Order),
122
2
                            kP224Order, kP224OrderRR, kP224OrderN0);
123
124
2
#if defined(BORINGSSL_HAS_UINT128) && !defined(OPENSSL_SMALL)
125
2
  out->meth = EC_GFp_nistp224_method();
126
2
  OPENSSL_memcpy(out->generator.raw.X.words, kP224GX, sizeof(kP224GX));
127
2
  OPENSSL_memcpy(out->generator.raw.Y.words, kP224GY, sizeof(kP224GY));
128
2
  out->generator.raw.Z.words[0] = 1;
129
2
  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
2
  out->generator.group = out;
138
139
2
  ec_group_set_a_minus3(out);
140
2
  out->has_order = 1;
141
2
  out->field_greater_than_order = 1;
142
2
}
143
144
2
DEFINE_METHOD_FUNCTION(EC_GROUP, EC_group_p256) {
145
2
  out->curve_name = NID_X9_62_prime256v1;
146
2
  out->comment = "NIST P-256";
147
  // 1.2.840.10045.3.1.7
148
2
  static const uint8_t kOIDP256[] = {0x2a, 0x86, 0x48, 0xce,
149
2
                                     0x3d, 0x03, 0x01, 0x07};
150
2
  OPENSSL_memcpy(out->oid, kOIDP256, sizeof(kOIDP256));
151
2
  out->oid_len = sizeof(kOIDP256);
152
153
2
  ec_group_init_static_mont(&out->field, OPENSSL_ARRAY_SIZE(kP256Field),
154
2
                            kP256Field, kP256FieldRR, kP256FieldN0);
155
2
  ec_group_init_static_mont(&out->order, OPENSSL_ARRAY_SIZE(kP256Order),
156
2
                            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
2
  out->meth = EC_GFp_nistp256_method();
164
2
#endif
165
2
  out->generator.group = out;
166
2
  OPENSSL_memcpy(out->generator.raw.X.words, kP256MontGX, sizeof(kP256MontGX));
167
2
  OPENSSL_memcpy(out->generator.raw.Y.words, kP256MontGY, sizeof(kP256MontGY));
168
2
  OPENSSL_memcpy(out->generator.raw.Z.words, kP256FieldR, sizeof(kP256FieldR));
169
2
  OPENSSL_memcpy(out->b.words, kP256MontB, sizeof(kP256MontB));
170
171
2
  ec_group_set_a_minus3(out);
172
2
  out->has_order = 1;
173
2
  out->field_greater_than_order = 1;
174
2
}
175
176
2
DEFINE_METHOD_FUNCTION(EC_GROUP, EC_group_p384) {
177
2
  out->curve_name = NID_secp384r1;
178
2
  out->comment = "NIST P-384";
179
  // 1.3.132.0.34
180
2
  static const uint8_t kOIDP384[] = {0x2b, 0x81, 0x04, 0x00, 0x22};
181
2
  OPENSSL_memcpy(out->oid, kOIDP384, sizeof(kOIDP384));
182
2
  out->oid_len = sizeof(kOIDP384);
183
184
2
  ec_group_init_static_mont(&out->field, OPENSSL_ARRAY_SIZE(kP384Field),
185
2
                            kP384Field, kP384FieldRR, kP384FieldN0);
186
2
  ec_group_init_static_mont(&out->order, OPENSSL_ARRAY_SIZE(kP384Order),
187
2
                            kP384Order, kP384OrderRR, kP384OrderN0);
188
189
2
  out->meth = EC_GFp_mont_method();
190
2
  out->generator.group = out;
191
2
  OPENSSL_memcpy(out->generator.raw.X.words, kP384MontGX, sizeof(kP384MontGX));
192
2
  OPENSSL_memcpy(out->generator.raw.Y.words, kP384MontGY, sizeof(kP384MontGY));
193
2
  OPENSSL_memcpy(out->generator.raw.Z.words, kP384FieldR, sizeof(kP384FieldR));
194
2
  OPENSSL_memcpy(out->b.words, kP384MontB, sizeof(kP384MontB));
195
196
2
  ec_group_set_a_minus3(out);
197
2
  out->has_order = 1;
198
2
  out->field_greater_than_order = 1;
199
2
}
200
201
2
DEFINE_METHOD_FUNCTION(EC_GROUP, EC_group_p521) {
202
2
  out->curve_name = NID_secp521r1;
203
2
  out->comment = "NIST P-521";
204
  // 1.3.132.0.35
205
2
  static const uint8_t kOIDP521[] = {0x2b, 0x81, 0x04, 0x00, 0x23};
206
2
  OPENSSL_memcpy(out->oid, kOIDP521, sizeof(kOIDP521));
207
2
  out->oid_len = sizeof(kOIDP521);
208
209
2
  ec_group_init_static_mont(&out->field, OPENSSL_ARRAY_SIZE(kP521Field),
210
2
                            kP521Field, kP521FieldRR, kP521FieldN0);
211
2
  ec_group_init_static_mont(&out->order, OPENSSL_ARRAY_SIZE(kP521Order),
212
2
                            kP521Order, kP521OrderRR, kP521OrderN0);
213
214
2
  out->meth = EC_GFp_mont_method();
215
2
  out->generator.group = out;
216
2
  OPENSSL_memcpy(out->generator.raw.X.words, kP521MontGX, sizeof(kP521MontGX));
217
2
  OPENSSL_memcpy(out->generator.raw.Y.words, kP521MontGY, sizeof(kP521MontGY));
218
2
  OPENSSL_memcpy(out->generator.raw.Z.words, kP521FieldR, sizeof(kP521FieldR));
219
2
  OPENSSL_memcpy(out->b.words, kP521MontB, sizeof(kP521MontB));
220
221
2
  ec_group_set_a_minus3(out);
222
2
  out->has_order = 1;
223
2
  out->field_greater_than_order = 1;
224
2
}
225
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
274
int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
275
0
                           const BIGNUM *order, const BIGNUM *cofactor) {
276
0
  if (group->curve_name != NID_undef || group->has_order ||
277
0
      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
0
    OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
283
0
    return 0;
284
0
  }
285
286
0
  if (BN_num_bytes(order) > EC_MAX_BYTES) {
287
0
    OPENSSL_PUT_ERROR(EC, EC_R_INVALID_GROUP_ORDER);
288
0
    return 0;
289
0
  }
290
291
  // Require a cofactor of one for custom curves, which implies prime order.
292
0
  if (!BN_is_one(cofactor)) {
293
0
    OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COFACTOR);
294
0
    return 0;
295
0
  }
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
0
  int ret = 0;
303
0
  BIGNUM *tmp = BN_new();
304
0
  if (tmp == NULL ||
305
0
      !BN_lshift1(tmp, order)) {
306
0
    goto err;
307
0
  }
308
0
  if (BN_cmp(tmp, &group->field.N) <= 0) {
309
0
    OPENSSL_PUT_ERROR(EC, EC_R_INVALID_GROUP_ORDER);
310
0
    goto err;
311
0
  }
312
313
0
  EC_AFFINE affine;
314
0
  if (!ec_jacobian_to_affine(group, &affine, &generator->raw) ||
315
0
      !BN_MONT_CTX_set(&group->order, order, NULL)) {
316
0
    goto err;
317
0
  }
318
319
0
  group->field_greater_than_order = BN_cmp(&group->field.N, order) > 0;
320
0
  group->generator.raw.X = affine.X;
321
0
  group->generator.raw.Y = affine.Y;
322
  // |raw.Z| was set to 1 by |EC_GROUP_new_curve_GFp|.
323
0
  group->has_order = 1;
324
0
  ret = 1;
325
326
0
err:
327
0
  BN_free(tmp);
328
0
  return ret;
329
0
}
330
331
614
EC_GROUP *EC_GROUP_new_by_curve_name(int nid) {
332
614
  switch (nid) {
333
49
    case NID_secp224r1:
334
49
      return (EC_GROUP *)EC_group_p224();
335
105
    case NID_X9_62_prime256v1:
336
105
      return (EC_GROUP *)EC_group_p256();
337
143
    case NID_secp384r1:
338
143
      return (EC_GROUP *)EC_group_p384();
339
108
    case NID_secp521r1:
340
108
      return (EC_GROUP *)EC_group_p521();
341
209
    default:
342
209
      OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
343
209
      return NULL;
344
614
  }
345
614
}
346
347
2.16k
void EC_GROUP_free(EC_GROUP *group) {
348
2.16k
  if (group == NULL ||
349
      // Built-in curves are static.
350
2.16k
      group->curve_name != NID_undef ||
351
2.16k
      !CRYPTO_refcount_dec_and_test_zero(&group->references)) {
352
2.16k
    return;
353
2.16k
  }
354
355
0
  bn_mont_ctx_cleanup(&group->order);
356
0
  bn_mont_ctx_cleanup(&group->field);
357
0
  OPENSSL_free(group);
358
0
}
359
360
1.06k
EC_GROUP *EC_GROUP_dup(const EC_GROUP *a) {
361
1.06k
  if (a == NULL ||
362
      // Built-in curves are static.
363
1.06k
      a->curve_name != NID_undef) {
364
1.06k
    return (EC_GROUP *)a;
365
1.06k
  }
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
0
  EC_GROUP *group = (EC_GROUP *)a;
370
0
  CRYPTO_refcount_inc(&group->references);
371
0
  return group;
372
1.06k
}
373
374
1.18k
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
1.18k
  if (a == b) {
377
1.18k
    return 0;
378
1.18k
  }
379
0
  if (a->curve_name != b->curve_name) {
380
0
    return 1;
381
0
  }
382
0
  if (a->curve_name != NID_undef) {
383
    // Built-in curves may be compared by curve name alone.
384
0
    return 0;
385
0
  }
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
0
  return a->meth != b->meth ||  //
392
0
         !a->has_order || !b->has_order ||
393
0
         BN_cmp(&a->order.N, &b->order.N) != 0 ||
394
0
         BN_cmp(&a->field.N, &b->field.N) != 0 ||
395
0
         !ec_felem_equal(a, &a->a, &b->a) ||  //
396
0
         !ec_felem_equal(a, &a->b, &b->b) ||
397
0
         !ec_GFp_simple_points_equal(a, &a->generator.raw, &b->generator.raw);
398
0
}
399
400
const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) {
401
  return group->has_order ? &group->generator : NULL;
402
}
403
404
64
const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group) {
405
64
  assert(group->has_order);
406
64
  return &group->order.N;
407
64
}
408
409
0
int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) {
410
0
  if (BN_copy(order, EC_GROUP_get0_order(group)) == NULL) {
411
0
    return 0;
412
0
  }
413
0
  return 1;
414
0
}
415
416
50
int EC_GROUP_order_bits(const EC_GROUP *group) {
417
50
  return BN_num_bits(&group->order.N);
418
50
}
419
420
int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
421
0
                          BN_CTX *ctx) {
422
  // All |EC_GROUP|s have cofactor 1.
423
0
  return BN_set_word(cofactor, 1);
424
0
}
425
426
int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *out_p, BIGNUM *out_a,
427
0
                           BIGNUM *out_b, BN_CTX *ctx) {
428
0
  return ec_GFp_simple_group_get_curve(group, out_p, out_a, out_b);
429
0
}
430
431
1.34k
int EC_GROUP_get_curve_name(const EC_GROUP *group) { return group->curve_name; }
432
433
unsigned EC_GROUP_get_degree(const EC_GROUP *group) {
434
  return BN_num_bits(&group->field.N);
435
}
436
437
0
const char *EC_curve_nid2nist(int nid) {
438
0
  switch (nid) {
439
0
    case NID_secp224r1:
440
0
      return "P-224";
441
0
    case NID_X9_62_prime256v1:
442
0
      return "P-256";
443
0
    case NID_secp384r1:
444
0
      return "P-384";
445
0
    case NID_secp521r1:
446
0
      return "P-521";
447
0
  }
448
0
  return NULL;
449
0
}
450
451
0
int EC_curve_nist2nid(const char *name) {
452
0
  if (strcmp(name, "P-224") == 0) {
453
0
    return NID_secp224r1;
454
0
  }
455
0
  if (strcmp(name, "P-256") == 0) {
456
0
    return NID_X9_62_prime256v1;
457
0
  }
458
0
  if (strcmp(name, "P-384") == 0) {
459
0
    return NID_secp384r1;
460
0
  }
461
0
  if (strcmp(name, "P-521") == 0) {
462
0
    return NID_secp521r1;
463
0
  }
464
0
  return NID_undef;
465
0
}
466
467
936
EC_POINT *EC_POINT_new(const EC_GROUP *group) {
468
936
  if (group == NULL) {
469
0
    OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
470
0
    return NULL;
471
0
  }
472
473
936
  EC_POINT *ret = OPENSSL_malloc(sizeof *ret);
474
936
  if (ret == NULL) {
475
0
    return NULL;
476
0
  }
477
478
936
  ret->group = EC_GROUP_dup(group);
479
936
  ec_GFp_simple_point_init(&ret->raw);
480
936
  return ret;
481
936
}
482
483
1.47k
static void ec_point_free(EC_POINT *point, int free_group) {
484
1.47k
  if (!point) {
485
534
    return;
486
534
  }
487
936
  if (free_group) {
488
936
    EC_GROUP_free(point->group);
489
936
  }
490
936
  OPENSSL_free(point);
491
936
}
492
493
1.47k
void EC_POINT_free(EC_POINT *point) {
494
1.47k
  ec_point_free(point, 1 /* free group */);
495
1.47k
}
496
497
0
void EC_POINT_clear_free(EC_POINT *point) { EC_POINT_free(point); }
498
499
460
int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) {
500
460
  if (EC_GROUP_cmp(dest->group, src->group, NULL) != 0) {
501
0
    OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
502
0
    return 0;
503
0
  }
504
460
  if (dest == src) {
505
0
    return 1;
506
0
  }
507
460
  ec_GFp_simple_point_copy(&dest->raw, &src->raw);
508
460
  return 1;
509
460
}
510
511
43
EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) {
512
43
  if (a == NULL) {
513
0
    return NULL;
514
0
  }
515
516
43
  EC_POINT *ret = EC_POINT_new(group);
517
43
  if (ret == NULL ||
518
43
      !EC_POINT_copy(ret, a)) {
519
0
    EC_POINT_free(ret);
520
0
    return NULL;
521
0
  }
522
523
43
  return ret;
524
43
}
525
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
535
1
int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) {
536
1
  if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
537
0
    OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
538
0
    return 0;
539
0
  }
540
1
  return ec_GFp_simple_is_at_infinity(group, &point->raw);
541
1
}
542
543
int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
544
42
                         BN_CTX *ctx) {
545
42
  if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
546
0
    OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
547
0
    return 0;
548
0
  }
549
42
  return ec_GFp_simple_is_on_curve(group, &point->raw);
550
42
}
551
552
int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
553
3
                 BN_CTX *ctx) {
554
3
  if (EC_GROUP_cmp(group, a->group, NULL) != 0 ||
555
3
      EC_GROUP_cmp(group, b->group, NULL) != 0) {
556
0
    OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
557
0
    return -1;
558
0
  }
559
560
  // Note |EC_POINT_cmp| returns zero for equality and non-zero for inequality.
561
3
  return ec_GFp_simple_points_equal(group, &a->raw, &b->raw) ? 0 : 1;
562
3
}
563
564
int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
565
                                        const EC_POINT *point, BIGNUM *x,
566
92
                                        BIGNUM *y, BN_CTX *ctx) {
567
92
  if (group->meth->point_get_affine_coordinates == 0) {
568
0
    OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
569
0
    return 0;
570
0
  }
571
92
  if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
572
0
    OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
573
0
    return 0;
574
0
  }
575
92
  EC_FELEM x_felem, y_felem;
576
92
  if (!group->meth->point_get_affine_coordinates(group, &point->raw,
577
92
                                                 x == NULL ? NULL : &x_felem,
578
92
                                                 y == NULL ? NULL : &y_felem) ||
579
92
      (x != NULL && !ec_felem_to_bignum(group, x, &x_felem)) ||
580
92
      (y != NULL && !ec_felem_to_bignum(group, y, &y_felem))) {
581
1
    return 0;
582
1
  }
583
91
  return 1;
584
92
}
585
586
int EC_POINT_get_affine_coordinates(const EC_GROUP *group,
587
                                    const EC_POINT *point, BIGNUM *x, BIGNUM *y,
588
0
                                    BN_CTX *ctx) {
589
0
  return EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx);
590
0
}
591
592
void ec_affine_to_jacobian(const EC_GROUP *group, EC_JACOBIAN *out,
593
137
                           const EC_AFFINE *p) {
594
137
  out->X = p->X;
595
137
  out->Y = p->Y;
596
137
  out->Z = *ec_felem_one(group);
597
137
}
598
599
int ec_jacobian_to_affine(const EC_GROUP *group, EC_AFFINE *out,
600
0
                          const EC_JACOBIAN *p) {
601
0
  return group->meth->point_get_affine_coordinates(group, p, &out->X, &out->Y);
602
0
}
603
604
int ec_jacobian_to_affine_batch(const EC_GROUP *group, EC_AFFINE *out,
605
0
                                const EC_JACOBIAN *in, size_t num) {
606
0
  if (group->meth->jacobian_to_affine_batch == NULL) {
607
0
    OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
608
0
    return 0;
609
0
  }
610
0
  return group->meth->jacobian_to_affine_batch(group, out, in, num);
611
0
}
612
613
int ec_point_set_affine_coordinates(const EC_GROUP *group, EC_AFFINE *out,
614
281
                                    const EC_FELEM *x, const EC_FELEM *y) {
615
281
  void (*const felem_mul)(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a,
616
281
                          const EC_FELEM *b) = group->meth->felem_mul;
617
281
  void (*const felem_sqr)(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a) =
618
281
      group->meth->felem_sqr;
619
620
  // Check if the point is on the curve.
621
281
  EC_FELEM lhs, rhs;
622
281
  felem_sqr(group, &lhs, y);                   // lhs = y^2
623
281
  felem_sqr(group, &rhs, x);                   // rhs = x^2
624
281
  ec_felem_add(group, &rhs, &rhs, &group->a);  // rhs = x^2 + a
625
281
  felem_mul(group, &rhs, &rhs, x);             // rhs = x^3 + ax
626
281
  ec_felem_add(group, &rhs, &rhs, &group->b);  // rhs = x^3 + ax + b
627
281
  if (!ec_felem_equal(group, &lhs, &rhs)) {
628
144
    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
144
    if (group->has_order) {
634
144
      out->X = group->generator.raw.X;
635
144
      out->Y = group->generator.raw.Y;
636
144
    }
637
144
    return 0;
638
144
  }
639
640
137
  out->X = *x;
641
137
  out->Y = *y;
642
137
  return 1;
643
281
}
644
645
int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
646
                                        const BIGNUM *x, const BIGNUM *y,
647
380
                                        BN_CTX *ctx) {
648
380
  if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
649
0
    OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
650
0
    return 0;
651
0
  }
652
653
380
  if (x == NULL || y == NULL) {
654
0
    OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
655
0
    return 0;
656
0
  }
657
658
380
  EC_FELEM x_felem, y_felem;
659
380
  EC_AFFINE affine;
660
380
  if (!ec_bignum_to_felem(group, &x_felem, x) ||
661
380
      !ec_bignum_to_felem(group, &y_felem, y) ||
662
380
      !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
243
    ec_set_to_safe_point(group, &point->raw);
666
243
    return 0;
667
243
  }
668
669
137
  ec_affine_to_jacobian(group, &point->raw, &affine);
670
137
  return 1;
671
380
}
672
673
int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
674
                                    const BIGNUM *x, const BIGNUM *y,
675
0
                                    BN_CTX *ctx) {
676
0
  return EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx);
677
0
}
678
679
int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
680
9
                 const EC_POINT *b, BN_CTX *ctx) {
681
9
  if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
682
9
      EC_GROUP_cmp(group, a->group, NULL) != 0 ||
683
9
      EC_GROUP_cmp(group, b->group, NULL) != 0) {
684
0
    OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
685
0
    return 0;
686
0
  }
687
9
  group->meth->add(group, &r->raw, &a->raw, &b->raw);
688
9
  return 1;
689
9
}
690
691
int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
692
2
                 BN_CTX *ctx) {
693
2
  if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
694
2
      EC_GROUP_cmp(group, a->group, NULL) != 0) {
695
0
    OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
696
0
    return 0;
697
0
  }
698
2
  group->meth->dbl(group, &r->raw, &a->raw);
699
2
  return 1;
700
2
}
701
702
703
2
int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) {
704
2
  if (EC_GROUP_cmp(group, a->group, NULL) != 0) {
705
0
    OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
706
0
    return 0;
707
0
  }
708
2
  ec_GFp_simple_invert(group, &a->raw);
709
2
  return 1;
710
2
}
711
712
static int arbitrary_bignum_to_scalar(const EC_GROUP *group, EC_SCALAR *out,
713
79
                                      const BIGNUM *in, BN_CTX *ctx) {
714
79
  if (ec_bignum_to_scalar(group, out, in)) {
715
56
    return 1;
716
56
  }
717
718
23
  ERR_clear_error();
719
720
  // This is an unusual input, so we do not guarantee constant-time processing.
721
23
  BN_CTX_start(ctx);
722
23
  BIGNUM *tmp = BN_CTX_get(ctx);
723
23
  int ok = tmp != NULL &&
724
23
           BN_nnmod(tmp, in, EC_GROUP_get0_order(group), ctx) &&
725
23
           ec_bignum_to_scalar(group, out, tmp);
726
23
  BN_CTX_end(ctx);
727
23
  return ok;
728
79
}
729
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
79
                              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
79
  if ((g_scalar == NULL && p_scalar == NULL) ||
737
79
      (p == NULL) != (p_scalar == NULL))  {
738
0
    OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
739
0
    return 0;
740
0
  }
741
742
79
  if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
743
79
      (p != NULL && EC_GROUP_cmp(group, p->group, NULL) != 0)) {
744
0
    OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
745
0
    return 0;
746
0
  }
747
748
79
  int ret = 0;
749
79
  BN_CTX *new_ctx = NULL;
750
79
  if (ctx == NULL) {
751
79
    new_ctx = BN_CTX_new();
752
79
    if (new_ctx == NULL) {
753
0
      goto err;
754
0
    }
755
79
    ctx = new_ctx;
756
79
  }
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
79
  if (g_scalar != NULL) {
770
37
    EC_SCALAR scalar;
771
37
    if (!arbitrary_bignum_to_scalar(group, &scalar, g_scalar, ctx) ||
772
37
        !ec_point_mul_scalar_base(group, &r->raw, &scalar)) {
773
0
      goto err;
774
0
    }
775
37
  }
776
777
79
  if (p_scalar != NULL) {
778
42
    EC_SCALAR scalar;
779
42
    EC_JACOBIAN tmp;
780
42
    if (!arbitrary_bignum_to_scalar(group, &scalar, p_scalar, ctx) ||
781
42
        !ec_point_mul_scalar(group, &tmp, &p->raw, &scalar)) {
782
0
      goto err;
783
0
    }
784
42
    if (g_scalar == NULL) {
785
42
      OPENSSL_memcpy(&r->raw, &tmp, sizeof(EC_JACOBIAN));
786
42
    } else {
787
0
      group->meth->add(group, &r->raw, &r->raw, &tmp);
788
0
    }
789
42
  }
790
791
79
  ret = 1;
792
793
79
err:
794
79
  BN_CTX_free(new_ctx);
795
79
  return ret;
796
79
}
797
798
int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
799
79
                 const EC_POINT *p, const BIGNUM *p_scalar, BN_CTX *ctx) {
800
79
  boringssl_ensure_ecc_self_test();
801
802
79
  return ec_point_mul_no_self_test(group, r, g_scalar, p, p_scalar, ctx);
803
79
}
804
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
13
                               const EC_SCALAR *p_scalar) {
808
13
  if (g_scalar == NULL || p_scalar == NULL || p == NULL) {
809
0
    OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
810
0
    return 0;
811
0
  }
812
813
13
  if (group->meth->mul_public == NULL) {
814
4
    return group->meth->mul_public_batch(group, r, g_scalar, p, p_scalar, 1);
815
4
  }
816
817
9
  group->meth->mul_public(group, r, g_scalar, p, p_scalar);
818
9
  return 1;
819
13
}
820
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
0
                                     const EC_SCALAR *scalars, size_t num) {
825
0
  if (group->meth->mul_public_batch == NULL) {
826
0
    OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
827
0
    return 0;
828
0
  }
829
830
0
  return group->meth->mul_public_batch(group, r, g_scalar, points, scalars,
831
0
                                       num);
832
0
}
833
834
int ec_point_mul_scalar(const EC_GROUP *group, EC_JACOBIAN *r,
835
47
                        const EC_JACOBIAN *p, const EC_SCALAR *scalar) {
836
47
  if (p == NULL || scalar == NULL) {
837
0
    OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
838
0
    return 0;
839
0
  }
840
841
47
  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
47
  if (!ec_GFp_simple_is_on_curve(group, r)) {
846
0
    OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
847
0
    return 0;
848
0
  }
849
850
47
  return 1;
851
47
}
852
853
int ec_point_mul_scalar_base(const EC_GROUP *group, EC_JACOBIAN *r,
854
43
                             const EC_SCALAR *scalar) {
855
43
  if (scalar == NULL) {
856
0
    OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
857
0
    return 0;
858
0
  }
859
860
43
  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
43
  if (!constant_time_declassify_int(ec_GFp_simple_is_on_curve(group, r))) {
867
0
    OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
868
0
    return 0;
869
0
  }
870
871
43
  return 1;
872
43
}
873
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
0
                              const EC_SCALAR *scalar2) {
879
0
  if (group->meth->mul_batch == NULL) {
880
0
    OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
881
0
    return 0;
882
0
  }
883
884
0
  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
0
  if (!ec_GFp_simple_is_on_curve(group, r)) {
889
0
    OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
890
0
    return 0;
891
0
  }
892
893
0
  return 1;
894
0
}
895
896
int ec_init_precomp(const EC_GROUP *group, EC_PRECOMP *out,
897
0
                    const EC_JACOBIAN *p) {
898
0
  if (group->meth->init_precomp == NULL) {
899
0
    OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
900
0
    return 0;
901
0
  }
902
903
0
  return group->meth->init_precomp(group, out, p);
904
0
}
905
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
0
                                const EC_SCALAR *scalar2) {
911
0
  if (group->meth->mul_precomp == NULL) {
912
0
    OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
913
0
    return 0;
914
0
  }
915
916
0
  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
0
  if (!ec_GFp_simple_is_on_curve(group, r)) {
921
0
    OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
922
0
    return 0;
923
0
  }
924
925
0
  return 1;
926
0
}
927
928
void ec_point_select(const EC_GROUP *group, EC_JACOBIAN *out, BN_ULONG mask,
929
116k
                      const EC_JACOBIAN *a, const EC_JACOBIAN *b) {
930
116k
  ec_felem_select(group, &out->X, mask, &a->X, &b->X);
931
116k
  ec_felem_select(group, &out->Y, mask, &a->Y, &b->Y);
932
116k
  ec_felem_select(group, &out->Z, mask, &a->Z, &b->Z);
933
116k
}
934
935
void ec_affine_select(const EC_GROUP *group, EC_AFFINE *out, BN_ULONG mask,
936
0
                      const EC_AFFINE *a, const EC_AFFINE *b) {
937
0
  ec_felem_select(group, &out->X, mask, &a->X, &b->X);
938
0
  ec_felem_select(group, &out->Y, mask, &a->Y, &b->Y);
939
0
}
940
941
void ec_precomp_select(const EC_GROUP *group, EC_PRECOMP *out, BN_ULONG mask,
942
0
                       const EC_PRECOMP *a, const EC_PRECOMP *b) {
943
0
  static_assert(sizeof(out->comb) == sizeof(*out),
944
0
                "out->comb does not span the entire structure");
945
0
  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(out->comb); i++) {
946
0
    ec_affine_select(group, &out->comb[i], mask, &a->comb[i], &b->comb[i]);
947
0
  }
948
0
}
949
950
int ec_cmp_x_coordinate(const EC_GROUP *group, const EC_JACOBIAN *p,
951
13
                        const EC_SCALAR *r) {
952
13
  return group->meth->cmp_x_coordinate(group, p, r);
953
13
}
954
955
int ec_get_x_coordinate_as_scalar(const EC_GROUP *group, EC_SCALAR *out,
956
0
                                  const EC_JACOBIAN *p) {
957
0
  uint8_t bytes[EC_MAX_BYTES];
958
0
  size_t len;
959
0
  if (!ec_get_x_coordinate_as_bytes(group, bytes, &len, sizeof(bytes), p)) {
960
0
    return 0;
961
0
  }
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
0
  const BIGNUM *order = EC_GROUP_get0_order(group);
983
0
  BN_ULONG words[EC_MAX_WORDS + 1] = {0};
984
0
  bn_big_endian_to_words(words, order->width + 1, bytes, len);
985
0
  bn_reduce_once(out->words, words, /*carry=*/words[order->width], order->d,
986
0
                 order->width);
987
0
  return 1;
988
0
}
989
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
5
                                 const EC_JACOBIAN *p) {
993
5
  size_t len = BN_num_bytes(&group->field.N);
994
5
  assert(len <= EC_MAX_BYTES);
995
5
  if (max_out < len) {
996
0
    OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL);
997
0
    return 0;
998
0
  }
999
1000
5
  EC_FELEM x;
1001
5
  if (!group->meth->point_get_affine_coordinates(group, p, &x, NULL)) {
1002
0
    return 0;
1003
0
  }
1004
1005
5
  ec_felem_to_bytes(group, out, out_len, &x);
1006
5
  *out_len = len;
1007
5
  return 1;
1008
5
}
1009
1010
243
void ec_set_to_safe_point(const EC_GROUP *group, EC_JACOBIAN *out) {
1011
243
  if (group->has_order) {
1012
243
    ec_GFp_simple_point_copy(out, &group->generator.raw);
1013
243
  } 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
0
    ec_GFp_simple_point_set_to_infinity(group, out);
1018
0
  }
1019
243
}
1020
1021
0
void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) {}
1022
1023
2.29k
int EC_GROUP_get_asn1_flag(const EC_GROUP *group) {
1024
2.29k
  return OPENSSL_EC_NAMED_CURVE;
1025
2.29k
}
1026
1027
0
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
0
  return (const EC_METHOD *)0x12340000;
1032
0
}
1033
1034
0
int EC_METHOD_get_field_type(const EC_METHOD *meth) {
1035
0
  return NID_X9_62_prime_field;
1036
0
}
1037
1038
void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
1039
0
                                        point_conversion_form_t form) {
1040
0
  if (form != POINT_CONVERSION_UNCOMPRESSED) {
1041
0
    abort();
1042
0
  }
1043
0
}