Coverage Report

Created: 2026-06-28 06:23

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