Coverage Report

Created: 2026-08-28 07:25

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