summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/ec/ecp_nistz256.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/ec/ecp_nistz256.c')
-rw-r--r--src/lib/libcrypto/ec/ecp_nistz256.c1191
1 files changed, 0 insertions, 1191 deletions
diff --git a/src/lib/libcrypto/ec/ecp_nistz256.c b/src/lib/libcrypto/ec/ecp_nistz256.c
deleted file mode 100644
index 62aac44c64..0000000000
--- a/src/lib/libcrypto/ec/ecp_nistz256.c
+++ /dev/null
@@ -1,1191 +0,0 @@
1/* $OpenBSD: ecp_nistz256.c,v 1.14 2022/11/26 16:08:52 tb Exp $ */
2/* Copyright (c) 2014, Intel Corporation.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
15
16/* Developers and authors:
17 * Shay Gueron (1, 2), and Vlad Krasnov (1)
18 * (1) Intel Corporation, Israel Development Center
19 * (2) University of Haifa
20 * Reference:
21 * S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with
22 * 256 Bit Primes" */
23
24/*
25 * The following license applies to _booth_recode_w5() and
26 * _booth_recode_w7():
27 */
28/* Copyright (c) 2015, Google Inc.
29 *
30 * Permission to use, copy, modify, and/or distribute this software for any
31 * purpose with or without fee is hereby granted, provided that the above
32 * copyright notice and this permission notice appear in all copies.
33 *
34 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
35 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
36 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
37 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
38 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
39 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
40 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
41
42#include <string.h>
43
44#include <openssl/crypto.h>
45#include <openssl/bn.h>
46#include <openssl/ec.h>
47#include <openssl/err.h>
48
49#include "ec_local.h"
50
51#if BN_BITS2 != 64
52#define TOBN(hi,lo) lo,hi
53#else
54#define TOBN(hi,lo) ((BN_ULONG)hi << 32 | lo)
55#endif
56
57#if defined(__GNUC__)
58#define ALIGN32 __attribute((aligned(32)))
59#elif defined(_MSC_VER)
60#define ALIGN32 __declspec(align(32))
61#else
62#define ALIGN32
63#endif
64
65#define P256_LIMBS (256 / BN_BITS2)
66
67typedef struct {
68 BN_ULONG X[P256_LIMBS];
69 BN_ULONG Y[P256_LIMBS];
70 BN_ULONG Z[P256_LIMBS];
71} P256_POINT;
72
73typedef struct {
74 BN_ULONG X[P256_LIMBS];
75 BN_ULONG Y[P256_LIMBS];
76} P256_POINT_AFFINE;
77
78typedef P256_POINT_AFFINE PRECOMP256_ROW[64];
79
80/* structure for precomputed multiples of the generator */
81typedef struct ec_pre_comp_st {
82 const EC_GROUP *group; /* Parent EC_GROUP object */
83 size_t w; /* Window size */
84 /*
85 * Constant time access to the X and Y coordinates of the pre-computed,
86 * generator multiplies, in the Montgomery domain. Pre-calculated
87 * multiplies are stored in affine form.
88 */
89 PRECOMP256_ROW *precomp;
90 int references;
91} EC_PRE_COMP;
92
93/*
94 * Arithmetic on field elements using Almost Montgomery Multiplication. The
95 * "almost" means, in particular, that the inputs and outputs of these
96 * functions are in the range [0, 2**BN_BITS2), not [0, P). Only
97 * |ecp_nistz256_from_mont| outputs a fully reduced value in [0, P). Almost
98 * Montgomery Arithmetic is described clearly in "Efficient Software
99 * Implementations of Modular Exponentiation" by Shay Gueron.
100 */
101
102/* Modular neg: res = -a mod P, where res is not fully reduced. */
103void ecp_nistz256_neg(BN_ULONG res[P256_LIMBS],
104 const BN_ULONG a[P256_LIMBS]);
105/* Montgomery mul: res = a*b*2^-256 mod P, where res is not fully reduced. */
106void ecp_nistz256_mul_mont(BN_ULONG res[P256_LIMBS],
107 const BN_ULONG a[P256_LIMBS], const BN_ULONG b[P256_LIMBS]);
108/* Montgomery sqr: res = a*a*2^-256 mod P, where res is not fully reduced. */
109void ecp_nistz256_sqr_mont(BN_ULONG res[P256_LIMBS],
110 const BN_ULONG a[P256_LIMBS]);
111/* Convert a number from Montgomery domain, by multiplying with 1, where res
112 * will be fully reduced mod P. */
113void ecp_nistz256_from_mont(BN_ULONG res[P256_LIMBS],
114 const BN_ULONG in[P256_LIMBS]);
115
116/* Functions that perform constant time access to the precomputed tables */
117void ecp_nistz256_select_w5(P256_POINT *val, const P256_POINT *in_t,
118 int index);
119void ecp_nistz256_select_w7(P256_POINT_AFFINE *val,
120 const P256_POINT_AFFINE *in_t, int index);
121
122/* One converted into the Montgomery domain */
123static const BN_ULONG ONE[P256_LIMBS] = {
124 TOBN(0x00000000, 0x00000001), TOBN(0xffffffff, 0x00000000),
125 TOBN(0xffffffff, 0xffffffff), TOBN(0x00000000, 0xfffffffe)
126};
127
128static void *ecp_nistz256_pre_comp_dup(void *);
129static void ecp_nistz256_pre_comp_free(void *);
130static void ecp_nistz256_pre_comp_clear_free(void *);
131static EC_PRE_COMP *ecp_nistz256_pre_comp_new(const EC_GROUP *group);
132
133/* Precomputed tables for the default generator */
134#include "ecp_nistz256_table.h"
135
136/* This function looks at 5+1 scalar bits (5 current, 1 adjacent less
137 * significant bit), and recodes them into a signed digit for use in fast point
138 * multiplication: the use of signed rather than unsigned digits means that
139 * fewer points need to be precomputed, given that point inversion is easy (a
140 * precomputed point dP makes -dP available as well).
141 *
142 * BACKGROUND:
143 *
144 * Signed digits for multiplication were introduced by Booth ("A signed binary
145 * multiplication technique", Quart. Journ. Mech. and Applied Math., vol. IV,
146 * pt. 2 (1951), pp. 236-240), in that case for multiplication of integers.
147 * Booth's original encoding did not generally improve the density of nonzero
148 * digits over the binary representation, and was merely meant to simplify the
149 * handling of signed factors given in two's complement; but it has since been
150 * shown to be the basis of various signed-digit representations that do have
151 * further advantages, including the wNAF, using the following general
152 * approach:
153 *
154 * (1) Given a binary representation
155 *
156 * b_k ... b_2 b_1 b_0,
157 *
158 * of a nonnegative integer (b_k in {0, 1}), rewrite it in digits 0, 1, -1
159 * by using bit-wise subtraction as follows:
160 *
161 * b_k b_(k-1) ... b_2 b_1 b_0
162 * - b_k ... b_3 b_2 b_1 b_0
163 * -------------------------------------
164 * s_k b_(k-1) ... s_3 s_2 s_1 s_0
165 *
166 * A left-shift followed by subtraction of the original value yields a new
167 * representation of the same value, using signed bits s_i = b_(i+1) - b_i.
168 * This representation from Booth's paper has since appeared in the
169 * literature under a variety of different names including "reversed binary
170 * form", "alternating greedy expansion", "mutual opposite form", and
171 * "sign-alternating {+-1}-representation".
172 *
173 * An interesting property is that among the nonzero bits, values 1 and -1
174 * strictly alternate.
175 *
176 * (2) Various window schemes can be applied to the Booth representation of
177 * integers: for example, right-to-left sliding windows yield the wNAF
178 * (a signed-digit encoding independently discovered by various researchers
179 * in the 1990s), and left-to-right sliding windows yield a left-to-right
180 * equivalent of the wNAF (independently discovered by various researchers
181 * around 2004).
182 *
183 * To prevent leaking information through side channels in point multiplication,
184 * we need to recode the given integer into a regular pattern: sliding windows
185 * as in wNAFs won't do, we need their fixed-window equivalent -- which is a few
186 * decades older: we'll be using the so-called "modified Booth encoding" due to
187 * MacSorley ("High-speed arithmetic in binary computers", Proc. IRE, vol. 49
188 * (1961), pp. 67-91), in a radix-2^5 setting. That is, we always combine five
189 * signed bits into a signed digit:
190 *
191 * s_(4j + 4) s_(4j + 3) s_(4j + 2) s_(4j + 1) s_(4j)
192 *
193 * The sign-alternating property implies that the resulting digit values are
194 * integers from -16 to 16.
195 *
196 * Of course, we don't actually need to compute the signed digits s_i as an
197 * intermediate step (that's just a nice way to see how this scheme relates
198 * to the wNAF): a direct computation obtains the recoded digit from the
199 * six bits b_(4j + 4) ... b_(4j - 1).
200 *
201 * This function takes those five bits as an integer (0 .. 63), writing the
202 * recoded digit to *sign (0 for positive, 1 for negative) and *digit (absolute
203 * value, in the range 0 .. 8). Note that this integer essentially provides the
204 * input bits "shifted to the left" by one position: for example, the input to
205 * compute the least significant recoded digit, given that there's no bit b_-1,
206 * has to be b_4 b_3 b_2 b_1 b_0 0. */
207
208static unsigned int
209_booth_recode_w5(unsigned int in)
210{
211 unsigned int s, d;
212
213 /* sets all bits to MSB(in), 'in' seen as 6-bit value */
214 s = ~((in >> 5) - 1);
215 d = (1 << 6) - in - 1;
216 d = (d & s) | (in & ~s);
217 d = (d >> 1) + (d & 1);
218
219 return (d << 1) + (s & 1);
220}
221
222static unsigned int
223_booth_recode_w7(unsigned int in)
224{
225 unsigned int s, d;
226
227 /* sets all bits to MSB(in), 'in' seen as 8-bit value */
228 s = ~((in >> 7) - 1);
229 d = (1 << 8) - in - 1;
230 d = (d & s) | (in & ~s);
231 d = (d >> 1) + (d & 1);
232
233 return (d << 1) + (s & 1);
234}
235
236static void
237copy_conditional(BN_ULONG dst[P256_LIMBS], const BN_ULONG src[P256_LIMBS],
238 BN_ULONG move)
239{
240 BN_ULONG mask1 = -move;
241 BN_ULONG mask2 = ~mask1;
242
243 dst[0] = (src[0] & mask1) ^ (dst[0] & mask2);
244 dst[1] = (src[1] & mask1) ^ (dst[1] & mask2);
245 dst[2] = (src[2] & mask1) ^ (dst[2] & mask2);
246 dst[3] = (src[3] & mask1) ^ (dst[3] & mask2);
247 if (P256_LIMBS == 8) {
248 dst[4] = (src[4] & mask1) ^ (dst[4] & mask2);
249 dst[5] = (src[5] & mask1) ^ (dst[5] & mask2);
250 dst[6] = (src[6] & mask1) ^ (dst[6] & mask2);
251 dst[7] = (src[7] & mask1) ^ (dst[7] & mask2);
252 }
253}
254
255static BN_ULONG
256is_zero(BN_ULONG in)
257{
258 in |= (0 - in);
259 in = ~in;
260 in &= BN_MASK2;
261 in >>= BN_BITS2 - 1;
262 return in;
263}
264
265static BN_ULONG
266is_equal(const BN_ULONG a[P256_LIMBS], const BN_ULONG b[P256_LIMBS])
267{
268 BN_ULONG res;
269
270 res = a[0] ^ b[0];
271 res |= a[1] ^ b[1];
272 res |= a[2] ^ b[2];
273 res |= a[3] ^ b[3];
274 if (P256_LIMBS == 8) {
275 res |= a[4] ^ b[4];
276 res |= a[5] ^ b[5];
277 res |= a[6] ^ b[6];
278 res |= a[7] ^ b[7];
279 }
280
281 return is_zero(res);
282}
283
284static BN_ULONG
285is_one(const BIGNUM *z)
286{
287 BN_ULONG res = 0;
288 BN_ULONG *a = z->d;
289
290 if (z->top == (P256_LIMBS - P256_LIMBS / 8)) {
291 res = a[0] ^ ONE[0];
292 res |= a[1] ^ ONE[1];
293 res |= a[2] ^ ONE[2];
294 res |= a[3] ^ ONE[3];
295 if (P256_LIMBS == 8) {
296 res |= a[4] ^ ONE[4];
297 res |= a[5] ^ ONE[5];
298 res |= a[6] ^ ONE[6];
299 /*
300 * No check for a[7] (being zero) on 32-bit platforms,
301 * because value of "one" takes only 7 limbs.
302 */
303 }
304 res = is_zero(res);
305 }
306
307 return res;
308}
309
310static int
311ecp_nistz256_set_words(BIGNUM *a, BN_ULONG words[P256_LIMBS])
312{
313 if (!bn_wexpand(a, P256_LIMBS)) {
314 ECerror(ERR_R_MALLOC_FAILURE);
315 return 0;
316 }
317 memcpy(a->d, words, sizeof(BN_ULONG) * P256_LIMBS);
318 a->top = P256_LIMBS;
319 bn_correct_top(a);
320 return 1;
321}
322
323void ecp_nistz256_point_double(P256_POINT *r, const P256_POINT *a);
324void ecp_nistz256_point_add(P256_POINT *r, const P256_POINT *a,
325 const P256_POINT *b);
326void ecp_nistz256_point_add_affine(P256_POINT *r, const P256_POINT *a,
327 const P256_POINT_AFFINE *b);
328
329/* r = in^-1 mod p */
330static void
331ecp_nistz256_mod_inverse(BN_ULONG r[P256_LIMBS], const BN_ULONG in[P256_LIMBS])
332{
333 /*
334 * The poly is ffffffff 00000001 00000000 00000000 00000000 ffffffff
335 * ffffffff ffffffff. We use FLT and use poly-2 as exponent.
336 */
337 BN_ULONG p2[P256_LIMBS];
338 BN_ULONG p4[P256_LIMBS];
339 BN_ULONG p8[P256_LIMBS];
340 BN_ULONG p16[P256_LIMBS];
341 BN_ULONG p32[P256_LIMBS];
342 BN_ULONG res[P256_LIMBS];
343 unsigned int i;
344
345 ecp_nistz256_sqr_mont(res, in);
346 ecp_nistz256_mul_mont(p2, res, in); /* 3*p */
347
348 ecp_nistz256_sqr_mont(res, p2);
349 ecp_nistz256_sqr_mont(res, res);
350 ecp_nistz256_mul_mont(p4, res, p2); /* f*p */
351
352 ecp_nistz256_sqr_mont(res, p4);
353 ecp_nistz256_sqr_mont(res, res);
354 ecp_nistz256_sqr_mont(res, res);
355 ecp_nistz256_sqr_mont(res, res);
356 ecp_nistz256_mul_mont(p8, res, p4); /* ff*p */
357
358 ecp_nistz256_sqr_mont(res, p8);
359 for (i = 0; i < 7; i++)
360 ecp_nistz256_sqr_mont(res, res);
361 ecp_nistz256_mul_mont(p16, res, p8); /* ffff*p */
362
363 ecp_nistz256_sqr_mont(res, p16);
364 for (i = 0; i < 15; i++)
365 ecp_nistz256_sqr_mont(res, res);
366 ecp_nistz256_mul_mont(p32, res, p16); /* ffffffff*p */
367
368 ecp_nistz256_sqr_mont(res, p32);
369 for (i = 0; i < 31; i++)
370 ecp_nistz256_sqr_mont(res, res);
371 ecp_nistz256_mul_mont(res, res, in);
372
373 for (i = 0; i < 32 * 4; i++)
374 ecp_nistz256_sqr_mont(res, res);
375 ecp_nistz256_mul_mont(res, res, p32);
376
377 for (i = 0; i < 32; i++)
378 ecp_nistz256_sqr_mont(res, res);
379 ecp_nistz256_mul_mont(res, res, p32);
380
381 for (i = 0; i < 16; i++)
382 ecp_nistz256_sqr_mont(res, res);
383 ecp_nistz256_mul_mont(res, res, p16);
384
385 for (i = 0; i < 8; i++)
386 ecp_nistz256_sqr_mont(res, res);
387 ecp_nistz256_mul_mont(res, res, p8);
388
389 ecp_nistz256_sqr_mont(res, res);
390 ecp_nistz256_sqr_mont(res, res);
391 ecp_nistz256_sqr_mont(res, res);
392 ecp_nistz256_sqr_mont(res, res);
393 ecp_nistz256_mul_mont(res, res, p4);
394
395 ecp_nistz256_sqr_mont(res, res);
396 ecp_nistz256_sqr_mont(res, res);
397 ecp_nistz256_mul_mont(res, res, p2);
398
399 ecp_nistz256_sqr_mont(res, res);
400 ecp_nistz256_sqr_mont(res, res);
401 ecp_nistz256_mul_mont(res, res, in);
402
403 memcpy(r, res, sizeof(res));
404}
405
406/*
407 * ecp_nistz256_bignum_to_field_elem copies the contents of |in| to |out| and
408 * returns one if it fits. Otherwise it returns zero.
409 */
410static int
411ecp_nistz256_bignum_to_field_elem(BN_ULONG out[P256_LIMBS], const BIGNUM *in)
412{
413 if (in->top > P256_LIMBS)
414 return 0;
415
416 memset(out, 0, sizeof(BN_ULONG) * P256_LIMBS);
417 memcpy(out, in->d, sizeof(BN_ULONG) * in->top);
418 return 1;
419}
420
421/* r = sum(scalar[i]*point[i]) */
422static int
423ecp_nistz256_windowed_mul(const EC_GROUP *group, P256_POINT *r,
424 const BIGNUM **scalar, const EC_POINT **point, size_t num, BN_CTX *ctx)
425{
426 int ret = 0;
427 unsigned int i, j, index;
428 unsigned char (*p_str)[33] = NULL;
429 const unsigned int window_size = 5;
430 const unsigned int mask = (1 << (window_size + 1)) - 1;
431 unsigned int wvalue;
432 BN_ULONG tmp[P256_LIMBS];
433 /* avoid warning about ignored alignment for stack variable */
434#if defined(__GNUC__) && !defined(__OpenBSD__)
435 ALIGN32
436#endif
437 P256_POINT h;
438 const BIGNUM **scalars = NULL;
439 P256_POINT (*table)[16] = NULL;
440
441 if (posix_memalign((void **)&table, 64, num * sizeof(*table)) != 0 ||
442 (p_str = reallocarray(NULL, num, sizeof(*p_str))) == NULL ||
443 (scalars = reallocarray(NULL, num, sizeof(*scalars))) == NULL) {
444 ECerror(ERR_R_MALLOC_FAILURE);
445 goto err;
446 }
447
448 for (i = 0; i < num; i++) {
449 P256_POINT *row = table[i];
450
451 /*
452 * This is an unusual input, we don't guarantee
453 * constant-timeness.
454 */
455 if (BN_num_bits(scalar[i]) > 256 || BN_is_negative(scalar[i])) {
456 BIGNUM *mod;
457
458 if ((mod = BN_CTX_get(ctx)) == NULL)
459 goto err;
460 if (!BN_nnmod(mod, scalar[i], &group->order, ctx)) {
461 ECerror(ERR_R_BN_LIB);
462 goto err;
463 }
464 scalars[i] = mod;
465 } else
466 scalars[i] = scalar[i];
467
468 for (j = 0; j < scalars[i]->top * BN_BYTES; j += BN_BYTES) {
469 BN_ULONG d = scalars[i]->d[j / BN_BYTES];
470
471 p_str[i][j + 0] = d & 0xff;
472 p_str[i][j + 1] = (d >> 8) & 0xff;
473 p_str[i][j + 2] = (d >> 16) & 0xff;
474 p_str[i][j + 3] = (d >> 24) & 0xff;
475 if (BN_BYTES == 8) {
476 d >>= 32;
477 p_str[i][j + 4] = d & 0xff;
478 p_str[i][j + 5] = (d >> 8) & 0xff;
479 p_str[i][j + 6] = (d >> 16) & 0xff;
480 p_str[i][j + 7] = (d >> 24) & 0xff;
481 }
482 }
483 for (; j < 33; j++)
484 p_str[i][j] = 0;
485
486 /*
487 * table[0] is implicitly (0,0,0) (the point at infinity),
488 * therefore it is not stored. All other values are actually
489 * stored with an offset of -1 in table.
490 */
491
492 if (!ecp_nistz256_bignum_to_field_elem(row[1 - 1].X,
493 &point[i]->X) ||
494 !ecp_nistz256_bignum_to_field_elem(row[1 - 1].Y,
495 &point[i]->Y) ||
496 !ecp_nistz256_bignum_to_field_elem(row[1 - 1].Z,
497 &point[i]->Z)) {
498 ECerror(EC_R_COORDINATES_OUT_OF_RANGE);
499 goto err;
500 }
501
502 ecp_nistz256_point_double(&row[ 2 - 1], &row[ 1 - 1]);
503 ecp_nistz256_point_add(&row[ 3 - 1], &row[ 2 - 1], &row[1 - 1]);
504 ecp_nistz256_point_double(&row[ 4 - 1], &row[ 2 - 1]);
505 ecp_nistz256_point_double(&row[ 6 - 1], &row[ 3 - 1]);
506 ecp_nistz256_point_double(&row[ 8 - 1], &row[ 4 - 1]);
507 ecp_nistz256_point_double(&row[12 - 1], &row[ 6 - 1]);
508 ecp_nistz256_point_add(&row[ 5 - 1], &row[ 4 - 1], &row[1 - 1]);
509 ecp_nistz256_point_add(&row[ 7 - 1], &row[ 6 - 1], &row[1 - 1]);
510 ecp_nistz256_point_add(&row[ 9 - 1], &row[ 8 - 1], &row[1 - 1]);
511 ecp_nistz256_point_add(&row[13 - 1], &row[12 - 1], &row[1 - 1]);
512 ecp_nistz256_point_double(&row[14 - 1], &row[ 7 - 1]);
513 ecp_nistz256_point_double(&row[10 - 1], &row[ 5 - 1]);
514 ecp_nistz256_point_add(&row[15 - 1], &row[14 - 1], &row[1 - 1]);
515 ecp_nistz256_point_add(&row[11 - 1], &row[10 - 1], &row[1 - 1]);
516 ecp_nistz256_point_add(&row[16 - 1], &row[15 - 1], &row[1 - 1]);
517 }
518
519 index = 255;
520
521 wvalue = p_str[0][(index - 1) / 8];
522 wvalue = (wvalue >> ((index - 1) % 8)) & mask;
523
524 ecp_nistz256_select_w5(r, table[0], _booth_recode_w5(wvalue) >> 1);
525
526 while (index >= 5) {
527 for (i = (index == 255 ? 1 : 0); i < num; i++) {
528 unsigned int off = (index - 1) / 8;
529
530 wvalue = p_str[i][off] | p_str[i][off + 1] << 8;
531 wvalue = (wvalue >> ((index - 1) % 8)) & mask;
532
533 wvalue = _booth_recode_w5(wvalue);
534
535 ecp_nistz256_select_w5(&h, table[i], wvalue >> 1);
536
537 ecp_nistz256_neg(tmp, h.Y);
538 copy_conditional(h.Y, tmp, (wvalue & 1));
539
540 ecp_nistz256_point_add(r, r, &h);
541 }
542
543 index -= window_size;
544
545 ecp_nistz256_point_double(r, r);
546 ecp_nistz256_point_double(r, r);
547 ecp_nistz256_point_double(r, r);
548 ecp_nistz256_point_double(r, r);
549 ecp_nistz256_point_double(r, r);
550 }
551
552 /* Final window */
553 for (i = 0; i < num; i++) {
554 wvalue = p_str[i][0];
555 wvalue = (wvalue << 1) & mask;
556
557 wvalue = _booth_recode_w5(wvalue);
558
559 ecp_nistz256_select_w5(&h, table[i], wvalue >> 1);
560
561 ecp_nistz256_neg(tmp, h.Y);
562 copy_conditional(h.Y, tmp, wvalue & 1);
563
564 ecp_nistz256_point_add(r, r, &h);
565 }
566
567 ret = 1;
568 err:
569 free(table);
570 free(p_str);
571 free(scalars);
572 return ret;
573}
574
575/* Coordinates of G, for which we have precomputed tables */
576static const BN_ULONG def_xG[P256_LIMBS] = {
577 TOBN(0x79e730d4, 0x18a9143c), TOBN(0x75ba95fc, 0x5fedb601),
578 TOBN(0x79fb732b, 0x77622510), TOBN(0x18905f76, 0xa53755c6)
579};
580
581static const BN_ULONG def_yG[P256_LIMBS] = {
582 TOBN(0xddf25357, 0xce95560a), TOBN(0x8b4ab8e4, 0xba19e45c),
583 TOBN(0xd2e88688, 0xdd21f325), TOBN(0x8571ff18, 0x25885d85)
584};
585
586/*
587 * ecp_nistz256_is_affine_G returns one if |generator| is the standard, P-256
588 * generator.
589 */
590static int
591ecp_nistz256_is_affine_G(const EC_POINT *generator)
592{
593 return generator->X.top == P256_LIMBS &&
594 generator->Y.top == P256_LIMBS &&
595 is_equal(generator->X.d, def_xG) &&
596 is_equal(generator->Y.d, def_yG) &&
597 is_one(&generator->Z);
598}
599
600static int
601ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx)
602{
603 /*
604 * We precompute a table for a Booth encoded exponent (wNAF) based
605 * computation. Each table holds 64 values for safe access, with an
606 * implicit value of infinity at index zero. We use a window of size 7,
607 * and therefore require ceil(256/7) = 37 tables.
608 */
609 EC_POINT *P = NULL, *T = NULL;
610 BN_CTX *new_ctx = NULL;
611 const EC_POINT *generator;
612 EC_PRE_COMP *ec_pre_comp;
613 BIGNUM *order;
614 int ret = 0;
615 unsigned int i, j, k;
616 PRECOMP256_ROW *precomp = NULL;
617
618 /* if there is an old EC_PRE_COMP object, throw it away */
619 EC_EX_DATA_free_data(&group->extra_data, ecp_nistz256_pre_comp_dup,
620 ecp_nistz256_pre_comp_free, ecp_nistz256_pre_comp_clear_free);
621
622 generator = EC_GROUP_get0_generator(group);
623 if (generator == NULL) {
624 ECerror(EC_R_UNDEFINED_GENERATOR);
625 return 0;
626 }
627
628 if (ecp_nistz256_is_affine_G(generator)) {
629 /*
630 * No need to calculate tables for the standard generator
631 * because we have them statically.
632 */
633 return 1;
634 }
635
636 if ((ec_pre_comp = ecp_nistz256_pre_comp_new(group)) == NULL)
637 return 0;
638
639 if (ctx == NULL) {
640 ctx = new_ctx = BN_CTX_new();
641 if (ctx == NULL)
642 goto err;
643 }
644
645 BN_CTX_start(ctx);
646 order = BN_CTX_get(ctx);
647
648 if (order == NULL)
649 goto err;
650
651 if (!EC_GROUP_get_order(group, order, ctx))
652 goto err;
653
654 if (BN_is_zero(order)) {
655 ECerror(EC_R_UNKNOWN_ORDER);
656 goto err;
657 }
658
659 if (posix_memalign((void **)&precomp, 64, 37 * sizeof(*precomp)) != 0) {
660 ECerror(ERR_R_MALLOC_FAILURE);
661 goto err;
662 }
663
664 P = EC_POINT_new(group);
665 T = EC_POINT_new(group);
666 if (P == NULL || T == NULL)
667 goto err;
668
669 /*
670 * The zero entry is implicitly infinity, and we skip it, storing other
671 * values with -1 offset.
672 */
673 if (!EC_POINT_copy(T, generator))
674 goto err;
675
676 for (k = 0; k < 64; k++) {
677 if (!EC_POINT_copy(P, T))
678 goto err;
679 for (j = 0; j < 37; j++) {
680 /*
681 * It would be faster to use EC_POINTs_make_affine and
682 * make multiple points affine at the same time.
683 */
684 if (!EC_POINT_make_affine(group, P, ctx))
685 goto err;
686 if (!ecp_nistz256_bignum_to_field_elem(
687 precomp[j][k].X, &P->X) ||
688 !ecp_nistz256_bignum_to_field_elem(
689 precomp[j][k].Y, &P->Y)) {
690 ECerror(EC_R_COORDINATES_OUT_OF_RANGE);
691 goto err;
692 }
693 for (i = 0; i < 7; i++) {
694 if (!EC_POINT_dbl(group, P, P, ctx))
695 goto err;
696 }
697 }
698 if (!EC_POINT_add(group, T, T, generator, ctx))
699 goto err;
700 }
701
702 ec_pre_comp->group = group;
703 ec_pre_comp->w = 7;
704 ec_pre_comp->precomp = precomp;
705
706 if (!EC_EX_DATA_set_data(&group->extra_data, ec_pre_comp,
707 ecp_nistz256_pre_comp_dup, ecp_nistz256_pre_comp_free,
708 ecp_nistz256_pre_comp_clear_free)) {
709 goto err;
710 }
711
712 ec_pre_comp = NULL;
713 ret = 1;
714
715 err:
716 if (ctx != NULL)
717 BN_CTX_end(ctx);
718 BN_CTX_free(new_ctx);
719
720 ecp_nistz256_pre_comp_free(ec_pre_comp);
721 free(precomp);
722 EC_POINT_free(P);
723 EC_POINT_free(T);
724 return ret;
725}
726
727static int
728ecp_nistz256_set_from_affine(EC_POINT *out, const EC_GROUP *group,
729 const P256_POINT_AFFINE *in, BN_CTX *ctx)
730{
731 BIGNUM x, y;
732 BN_ULONG d_x[P256_LIMBS], d_y[P256_LIMBS];
733 int ret = 0;
734
735 memcpy(d_x, in->X, sizeof(d_x));
736 x.d = d_x;
737 x.dmax = x.top = P256_LIMBS;
738 x.neg = 0;
739 x.flags = BN_FLG_STATIC_DATA;
740
741 memcpy(d_y, in->Y, sizeof(d_y));
742 y.d = d_y;
743 y.dmax = y.top = P256_LIMBS;
744 y.neg = 0;
745 y.flags = BN_FLG_STATIC_DATA;
746
747 ret = EC_POINT_set_affine_coordinates(group, out, &x, &y, ctx);
748
749 return ret;
750}
751
752/* r = scalar*G + sum(scalars[i]*points[i]) */
753static int
754ecp_nistz256_points_mul(const EC_GROUP *group, EC_POINT *r,
755 const BIGNUM *scalar, size_t num, const EC_POINT *points[],
756 const BIGNUM *scalars[], BN_CTX *ctx)
757{
758 int ret = 0, no_precomp_for_generator = 0, p_is_infinity = 0;
759 size_t j;
760 unsigned char p_str[33] = { 0 };
761 const PRECOMP256_ROW *precomp = NULL;
762 const EC_PRE_COMP *ec_pre_comp = NULL;
763 const EC_POINT *generator = NULL;
764 unsigned int i = 0, index = 0;
765 BN_CTX *new_ctx = NULL;
766 const BIGNUM **new_scalars = NULL;
767 const EC_POINT **new_points = NULL;
768 const unsigned int window_size = 7;
769 const unsigned int mask = (1 << (window_size + 1)) - 1;
770 unsigned int wvalue;
771 /* avoid warning about ignored alignment for stack variable */
772#if defined(__GNUC__) && !defined(__OpenBSD__)
773 ALIGN32
774#endif
775 union {
776 P256_POINT p;
777 P256_POINT_AFFINE a;
778 } t, p;
779 BIGNUM *tmp_scalar;
780
781 if (group->meth != r->meth) {
782 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
783 return 0;
784 }
785
786 if (scalar == NULL && num == 0)
787 return EC_POINT_set_to_infinity(group, r);
788
789 for (j = 0; j < num; j++) {
790 if (group->meth != points[j]->meth) {
791 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
792 return 0;
793 }
794 }
795
796 if (ctx == NULL) {
797 ctx = new_ctx = BN_CTX_new();
798 if (ctx == NULL)
799 goto err;
800 }
801
802 BN_CTX_start(ctx);
803
804 if (scalar) {
805 generator = EC_GROUP_get0_generator(group);
806 if (generator == NULL) {
807 ECerror(EC_R_UNDEFINED_GENERATOR);
808 goto err;
809 }
810
811 /* look if we can use precomputed multiples of generator */
812 ec_pre_comp = EC_EX_DATA_get_data(group->extra_data,
813 ecp_nistz256_pre_comp_dup, ecp_nistz256_pre_comp_free,
814 ecp_nistz256_pre_comp_clear_free);
815 if (ec_pre_comp != NULL) {
816 /*
817 * If there is a precomputed table for the generator,
818 * check that it was generated with the same generator.
819 */
820 EC_POINT *pre_comp_generator = EC_POINT_new(group);
821 if (pre_comp_generator == NULL)
822 goto err;
823
824 if (!ecp_nistz256_set_from_affine(pre_comp_generator,
825 group, ec_pre_comp->precomp[0], ctx)) {
826 EC_POINT_free(pre_comp_generator);
827 goto err;
828 }
829
830 if (0 == EC_POINT_cmp(group, generator,
831 pre_comp_generator, ctx))
832 precomp = (const PRECOMP256_ROW *)
833 ec_pre_comp->precomp;
834
835 EC_POINT_free(pre_comp_generator);
836 }
837
838 if (precomp == NULL && ecp_nistz256_is_affine_G(generator)) {
839 /*
840 * If there is no precomputed data, but the generator
841 * is the default, a hardcoded table of precomputed
842 * data is used. This is because applications, such as
843 * Apache, do not use EC_KEY_precompute_mult.
844 */
845 precomp =
846 (const PRECOMP256_ROW *)ecp_nistz256_precomputed;
847 }
848
849 if (precomp) {
850 if (BN_num_bits(scalar) > 256 ||
851 BN_is_negative(scalar)) {
852 if ((tmp_scalar = BN_CTX_get(ctx)) == NULL)
853 goto err;
854
855 if (!BN_nnmod(tmp_scalar, scalar, &group->order,
856 ctx)) {
857 ECerror(ERR_R_BN_LIB);
858 goto err;
859 }
860 scalar = tmp_scalar;
861 }
862
863 for (i = 0; i < scalar->top * BN_BYTES; i += BN_BYTES) {
864 BN_ULONG d = scalar->d[i / BN_BYTES];
865
866 p_str[i + 0] = d & 0xff;
867 p_str[i + 1] = (d >> 8) & 0xff;
868 p_str[i + 2] = (d >> 16) & 0xff;
869 p_str[i + 3] = (d >> 24) & 0xff;
870 if (BN_BYTES == 8) {
871 d >>= 32;
872 p_str[i + 4] = d & 0xff;
873 p_str[i + 5] = (d >> 8) & 0xff;
874 p_str[i + 6] = (d >> 16) & 0xff;
875 p_str[i + 7] = (d >> 24) & 0xff;
876 }
877 }
878
879 for (; i < 33; i++)
880 p_str[i] = 0;
881
882 /* First window */
883 wvalue = (p_str[0] << 1) & mask;
884 index += window_size;
885
886 wvalue = _booth_recode_w7(wvalue);
887
888 ecp_nistz256_select_w7(&p.a, precomp[0], wvalue >> 1);
889
890 ecp_nistz256_neg(p.p.Z, p.p.Y);
891 copy_conditional(p.p.Y, p.p.Z, wvalue & 1);
892
893 /*
894 * Since affine infinity is encoded as (0,0) and
895 * Jacobian is (,,0), we need to harmonize them
896 * by assigning "one" or zero to Z.
897 */
898 BN_ULONG infty;
899 infty = (p.p.X[0] | p.p.X[1] | p.p.X[2] | p.p.X[3] |
900 p.p.Y[0] | p.p.Y[1] | p.p.Y[2] | p.p.Y[3]);
901 if (P256_LIMBS == 8)
902 infty |=
903 (p.p.X[4] | p.p.X[5] | p.p.X[6] | p.p.X[7] |
904 p.p.Y[4] | p.p.Y[5] | p.p.Y[6] | p.p.Y[7]);
905
906 infty = 0 - is_zero(infty);
907 infty = ~infty;
908
909 p.p.Z[0] = ONE[0] & infty;
910 p.p.Z[1] = ONE[1] & infty;
911 p.p.Z[2] = ONE[2] & infty;
912 p.p.Z[3] = ONE[3] & infty;
913 if (P256_LIMBS == 8) {
914 p.p.Z[4] = ONE[4] & infty;
915 p.p.Z[5] = ONE[5] & infty;
916 p.p.Z[6] = ONE[6] & infty;
917 p.p.Z[7] = ONE[7] & infty;
918 }
919
920 for (i = 1; i < 37; i++) {
921 unsigned int off = (index - 1) / 8;
922 wvalue = p_str[off] | p_str[off + 1] << 8;
923 wvalue = (wvalue >> ((index - 1) % 8)) & mask;
924 index += window_size;
925
926 wvalue = _booth_recode_w7(wvalue);
927
928 ecp_nistz256_select_w7(&t.a, precomp[i],
929 wvalue >> 1);
930
931 ecp_nistz256_neg(t.p.Z, t.a.Y);
932 copy_conditional(t.a.Y, t.p.Z, wvalue & 1);
933
934 ecp_nistz256_point_add_affine(&p.p, &p.p, &t.a);
935 }
936 } else {
937 p_is_infinity = 1;
938 no_precomp_for_generator = 1;
939 }
940 } else
941 p_is_infinity = 1;
942
943 if (no_precomp_for_generator) {
944 /*
945 * Without a precomputed table for the generator, it has to be
946 * handled like a normal point.
947 */
948 new_scalars = reallocarray(NULL, num + 1, sizeof(BIGNUM *));
949 new_points = reallocarray(NULL, num + 1, sizeof(EC_POINT *));
950 if (new_scalars == NULL || new_points == NULL) {
951 ECerror(ERR_R_MALLOC_FAILURE);
952 goto err;
953 }
954
955 memcpy(new_scalars, scalars, num * sizeof(BIGNUM *));
956 new_scalars[num] = scalar;
957 memcpy(new_points, points, num * sizeof(EC_POINT *));
958 new_points[num] = generator;
959
960 scalars = new_scalars;
961 points = new_points;
962 num++;
963 }
964
965 if (num != 0) {
966 P256_POINT *out = &t.p;
967 if (p_is_infinity)
968 out = &p.p;
969
970 if (!ecp_nistz256_windowed_mul(group, out, scalars, points, num,
971 ctx))
972 goto err;
973
974 if (!p_is_infinity)
975 ecp_nistz256_point_add(&p.p, &p.p, out);
976 }
977
978 /* Not constant-time, but we're only operating on the public output. */
979 if (!ecp_nistz256_set_words(&r->X, p.p.X) ||
980 !ecp_nistz256_set_words(&r->Y, p.p.Y) ||
981 !ecp_nistz256_set_words(&r->Z, p.p.Z)) {
982 goto err;
983 }
984 r->Z_is_one = is_one(&r->Z) & 1;
985
986 ret = 1;
987
988 err:
989 if (ctx)
990 BN_CTX_end(ctx);
991 BN_CTX_free(new_ctx);
992 free(new_points);
993 free(new_scalars);
994 return ret;
995}
996
997static int
998ecp_nistz256_get_affine(const EC_GROUP *group, const EC_POINT *point,
999 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
1000{
1001 BN_ULONG z_inv2[P256_LIMBS];
1002 BN_ULONG z_inv3[P256_LIMBS];
1003 BN_ULONG point_x[P256_LIMBS], point_y[P256_LIMBS], point_z[P256_LIMBS];
1004
1005 if (EC_POINT_is_at_infinity(group, point)) {
1006 ECerror(EC_R_POINT_AT_INFINITY);
1007 return 0;
1008 }
1009
1010 if (!ecp_nistz256_bignum_to_field_elem(point_x, &point->X) ||
1011 !ecp_nistz256_bignum_to_field_elem(point_y, &point->Y) ||
1012 !ecp_nistz256_bignum_to_field_elem(point_z, &point->Z)) {
1013 ECerror(EC_R_COORDINATES_OUT_OF_RANGE);
1014 return 0;
1015 }
1016
1017 ecp_nistz256_mod_inverse(z_inv3, point_z);
1018 ecp_nistz256_sqr_mont(z_inv2, z_inv3);
1019
1020 /*
1021 * Unlike the |BN_mod_mul_montgomery|-based implementation, we cannot
1022 * factor out the two calls to |ecp_nistz256_from_mont| into one call,
1023 * because |ecp_nistz256_from_mont| must be the last operation to
1024 * ensure that the result is fully reduced mod P.
1025 */
1026 if (x != NULL) {
1027 BN_ULONG x_aff[P256_LIMBS];
1028 BN_ULONG x_ret[P256_LIMBS];
1029
1030 ecp_nistz256_mul_mont(x_aff, z_inv2, point_x);
1031 ecp_nistz256_from_mont(x_ret, x_aff);
1032 if (!ecp_nistz256_set_words(x, x_ret))
1033 return 0;
1034 }
1035
1036 if (y != NULL) {
1037 BN_ULONG y_aff[P256_LIMBS];
1038 BN_ULONG y_ret[P256_LIMBS];
1039
1040 ecp_nistz256_mul_mont(z_inv3, z_inv3, z_inv2);
1041 ecp_nistz256_mul_mont(y_aff, z_inv3, point_y);
1042 ecp_nistz256_from_mont(y_ret, y_aff);
1043 if (!ecp_nistz256_set_words(y, y_ret))
1044 return 0;
1045 }
1046
1047 return 1;
1048}
1049
1050static EC_PRE_COMP *
1051ecp_nistz256_pre_comp_new(const EC_GROUP *group)
1052{
1053 EC_PRE_COMP *ret;
1054
1055 if (group == NULL)
1056 return NULL;
1057
1058 ret = (EC_PRE_COMP *)malloc(sizeof(EC_PRE_COMP));
1059 if (ret == NULL) {
1060 ECerror(ERR_R_MALLOC_FAILURE);
1061 return ret;
1062 }
1063
1064 ret->group = group;
1065 ret->w = 6; /* default */
1066 ret->precomp = NULL;
1067 ret->references = 1;
1068 return ret;
1069}
1070
1071static void *
1072ecp_nistz256_pre_comp_dup(void *src_)
1073{
1074 EC_PRE_COMP *src = src_;
1075
1076 /* no need to actually copy, these objects never change! */
1077 CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP);
1078
1079 return src_;
1080}
1081
1082static void
1083ecp_nistz256_pre_comp_free(void *pre_)
1084{
1085 int i;
1086 EC_PRE_COMP *pre = pre_;
1087
1088 if (pre == NULL)
1089 return;
1090
1091 i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
1092 if (i > 0)
1093 return;
1094
1095 free(pre->precomp);
1096 free(pre);
1097}
1098
1099static void
1100ecp_nistz256_pre_comp_clear_free(void *pre_)
1101{
1102 int i;
1103 EC_PRE_COMP *pre = pre_;
1104
1105 if (pre == NULL)
1106 return;
1107
1108 i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
1109 if (i > 0)
1110 return;
1111
1112 if (pre->precomp != NULL) {
1113 /*
1114 * LSSL XXX
1115 * The original OpenSSL code uses an obfuscated
1116 * computation which is intended to be
1117 * 37 * (1 << pre->w) * sizeof(P256_POINT_AFFINE)
1118 * here, but the only place where we allocate this uses
1119 * PRECOMP256_ROW (i.e. 64 P256_POINT_AFFINE) but sets w == 7.
1120 */
1121 freezero(pre->precomp, 37 * sizeof(PRECOMP256_ROW));
1122 }
1123 freezero(pre, sizeof *pre);
1124}
1125
1126static int
1127ecp_nistz256_window_have_precompute_mult(const EC_GROUP *group)
1128{
1129 /* There is a hard-coded table for the default generator. */
1130 const EC_POINT *generator = EC_GROUP_get0_generator(group);
1131 if (generator != NULL && ecp_nistz256_is_affine_G(generator)) {
1132 /* There is a hard-coded table for the default generator. */
1133 return 1;
1134 }
1135
1136 return
1137 EC_EX_DATA_get_data(group->extra_data, ecp_nistz256_pre_comp_dup,
1138 ecp_nistz256_pre_comp_free, ecp_nistz256_pre_comp_clear_free) !=
1139 NULL;
1140}
1141
1142const EC_METHOD *
1143EC_GFp_nistz256_method(void)
1144{
1145 static const EC_METHOD ret = {
1146 .flags = EC_FLAGS_DEFAULT_OCT,
1147 .field_type = NID_X9_62_prime_field,
1148 .group_init = ec_GFp_mont_group_init,
1149 .group_finish = ec_GFp_mont_group_finish,
1150 .group_clear_finish = ec_GFp_mont_group_clear_finish,
1151 .group_copy = ec_GFp_mont_group_copy,
1152 .group_set_curve = ec_GFp_mont_group_set_curve,
1153 .group_get_curve = ec_GFp_simple_group_get_curve,
1154 .group_get_degree = ec_GFp_simple_group_get_degree,
1155 .group_order_bits = ec_group_simple_order_bits,
1156 .group_check_discriminant =
1157 ec_GFp_simple_group_check_discriminant,
1158 .point_init = ec_GFp_simple_point_init,
1159 .point_finish = ec_GFp_simple_point_finish,
1160 .point_clear_finish = ec_GFp_simple_point_clear_finish,
1161 .point_copy = ec_GFp_simple_point_copy,
1162 .point_set_to_infinity = ec_GFp_simple_point_set_to_infinity,
1163 .point_set_Jprojective_coordinates =
1164 ec_GFp_simple_set_Jprojective_coordinates,
1165 .point_get_Jprojective_coordinates =
1166 ec_GFp_simple_get_Jprojective_coordinates,
1167 .point_set_affine_coordinates =
1168 ec_GFp_simple_point_set_affine_coordinates,
1169 .point_get_affine_coordinates = ecp_nistz256_get_affine,
1170 .add = ec_GFp_simple_add,
1171 .dbl = ec_GFp_simple_dbl,
1172 .invert = ec_GFp_simple_invert,
1173 .is_at_infinity = ec_GFp_simple_is_at_infinity,
1174 .is_on_curve = ec_GFp_simple_is_on_curve,
1175 .point_cmp = ec_GFp_simple_cmp,
1176 .make_affine = ec_GFp_simple_make_affine,
1177 .points_make_affine = ec_GFp_simple_points_make_affine,
1178 .mul = ecp_nistz256_points_mul,
1179 .precompute_mult = ecp_nistz256_mult_precompute,
1180 .have_precompute_mult =
1181 ecp_nistz256_window_have_precompute_mult,
1182 .field_mul = ec_GFp_mont_field_mul,
1183 .field_sqr = ec_GFp_mont_field_sqr,
1184 .field_encode = ec_GFp_mont_field_encode,
1185 .field_decode = ec_GFp_mont_field_decode,
1186 .field_set_to_one = ec_GFp_mont_field_set_to_one,
1187 .blind_coordinates = NULL,
1188 };
1189
1190 return &ret;
1191}