1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
4e1051a39Sopenharmony_ci *
5e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
6e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
7e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
8e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
9e1051a39Sopenharmony_ci */
10e1051a39Sopenharmony_ci
11e1051a39Sopenharmony_ci/*
12e1051a39Sopenharmony_ci * ECDSA low level APIs are deprecated for public use, but still ok for
13e1051a39Sopenharmony_ci * internal use.
14e1051a39Sopenharmony_ci */
15e1051a39Sopenharmony_ci#include "internal/deprecated.h"
16e1051a39Sopenharmony_ci
17e1051a39Sopenharmony_ci#include <string.h>
18e1051a39Sopenharmony_ci#include <openssl/err.h>
19e1051a39Sopenharmony_ci
20e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
21e1051a39Sopenharmony_ci#include "crypto/bn.h"
22e1051a39Sopenharmony_ci#include "ec_local.h"
23e1051a39Sopenharmony_ci#include "internal/refcount.h"
24e1051a39Sopenharmony_ci
25e1051a39Sopenharmony_ci/*
26e1051a39Sopenharmony_ci * This file implements the wNAF-based interleaving multi-exponentiation method
27e1051a39Sopenharmony_ci * Formerly at:
28e1051a39Sopenharmony_ci *   http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#multiexp
29e1051a39Sopenharmony_ci * You might now find it here:
30e1051a39Sopenharmony_ci *   http://link.springer.com/chapter/10.1007%2F3-540-45537-X_13
31e1051a39Sopenharmony_ci *   http://www.bmoeller.de/pdf/TI-01-08.multiexp.pdf
32e1051a39Sopenharmony_ci * For multiplication with precomputation, we use wNAF splitting, formerly at:
33e1051a39Sopenharmony_ci *   http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#fastexp
34e1051a39Sopenharmony_ci */
35e1051a39Sopenharmony_ci
36e1051a39Sopenharmony_ci/* structure for precomputed multiples of the generator */
37e1051a39Sopenharmony_cistruct ec_pre_comp_st {
38e1051a39Sopenharmony_ci    const EC_GROUP *group;      /* parent EC_GROUP object */
39e1051a39Sopenharmony_ci    size_t blocksize;           /* block size for wNAF splitting */
40e1051a39Sopenharmony_ci    size_t numblocks;           /* max. number of blocks for which we have
41e1051a39Sopenharmony_ci                                 * precomputation */
42e1051a39Sopenharmony_ci    size_t w;                   /* window size */
43e1051a39Sopenharmony_ci    EC_POINT **points;          /* array with pre-calculated multiples of
44e1051a39Sopenharmony_ci                                 * generator: 'num' pointers to EC_POINT
45e1051a39Sopenharmony_ci                                 * objects followed by a NULL */
46e1051a39Sopenharmony_ci    size_t num;                 /* numblocks * 2^(w-1) */
47e1051a39Sopenharmony_ci    CRYPTO_REF_COUNT references;
48e1051a39Sopenharmony_ci    CRYPTO_RWLOCK *lock;
49e1051a39Sopenharmony_ci};
50e1051a39Sopenharmony_ci
51e1051a39Sopenharmony_cistatic EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group)
52e1051a39Sopenharmony_ci{
53e1051a39Sopenharmony_ci    EC_PRE_COMP *ret = NULL;
54e1051a39Sopenharmony_ci
55e1051a39Sopenharmony_ci    if (!group)
56e1051a39Sopenharmony_ci        return NULL;
57e1051a39Sopenharmony_ci
58e1051a39Sopenharmony_ci    ret = OPENSSL_zalloc(sizeof(*ret));
59e1051a39Sopenharmony_ci    if (ret == NULL) {
60e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
61e1051a39Sopenharmony_ci        return ret;
62e1051a39Sopenharmony_ci    }
63e1051a39Sopenharmony_ci
64e1051a39Sopenharmony_ci    ret->group = group;
65e1051a39Sopenharmony_ci    ret->blocksize = 8;         /* default */
66e1051a39Sopenharmony_ci    ret->w = 4;                 /* default */
67e1051a39Sopenharmony_ci    ret->references = 1;
68e1051a39Sopenharmony_ci
69e1051a39Sopenharmony_ci    ret->lock = CRYPTO_THREAD_lock_new();
70e1051a39Sopenharmony_ci    if (ret->lock == NULL) {
71e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
72e1051a39Sopenharmony_ci        OPENSSL_free(ret);
73e1051a39Sopenharmony_ci        return NULL;
74e1051a39Sopenharmony_ci    }
75e1051a39Sopenharmony_ci    return ret;
76e1051a39Sopenharmony_ci}
77e1051a39Sopenharmony_ci
78e1051a39Sopenharmony_ciEC_PRE_COMP *EC_ec_pre_comp_dup(EC_PRE_COMP *pre)
79e1051a39Sopenharmony_ci{
80e1051a39Sopenharmony_ci    int i;
81e1051a39Sopenharmony_ci    if (pre != NULL)
82e1051a39Sopenharmony_ci        CRYPTO_UP_REF(&pre->references, &i, pre->lock);
83e1051a39Sopenharmony_ci    return pre;
84e1051a39Sopenharmony_ci}
85e1051a39Sopenharmony_ci
86e1051a39Sopenharmony_civoid EC_ec_pre_comp_free(EC_PRE_COMP *pre)
87e1051a39Sopenharmony_ci{
88e1051a39Sopenharmony_ci    int i;
89e1051a39Sopenharmony_ci
90e1051a39Sopenharmony_ci    if (pre == NULL)
91e1051a39Sopenharmony_ci        return;
92e1051a39Sopenharmony_ci
93e1051a39Sopenharmony_ci    CRYPTO_DOWN_REF(&pre->references, &i, pre->lock);
94e1051a39Sopenharmony_ci    REF_PRINT_COUNT("EC_ec", pre);
95e1051a39Sopenharmony_ci    if (i > 0)
96e1051a39Sopenharmony_ci        return;
97e1051a39Sopenharmony_ci    REF_ASSERT_ISNT(i < 0);
98e1051a39Sopenharmony_ci
99e1051a39Sopenharmony_ci    if (pre->points != NULL) {
100e1051a39Sopenharmony_ci        EC_POINT **pts;
101e1051a39Sopenharmony_ci
102e1051a39Sopenharmony_ci        for (pts = pre->points; *pts != NULL; pts++)
103e1051a39Sopenharmony_ci            EC_POINT_free(*pts);
104e1051a39Sopenharmony_ci        OPENSSL_free(pre->points);
105e1051a39Sopenharmony_ci    }
106e1051a39Sopenharmony_ci    CRYPTO_THREAD_lock_free(pre->lock);
107e1051a39Sopenharmony_ci    OPENSSL_free(pre);
108e1051a39Sopenharmony_ci}
109e1051a39Sopenharmony_ci
110e1051a39Sopenharmony_ci#define EC_POINT_BN_set_flags(P, flags) do { \
111e1051a39Sopenharmony_ci    BN_set_flags((P)->X, (flags)); \
112e1051a39Sopenharmony_ci    BN_set_flags((P)->Y, (flags)); \
113e1051a39Sopenharmony_ci    BN_set_flags((P)->Z, (flags)); \
114e1051a39Sopenharmony_ci} while(0)
115e1051a39Sopenharmony_ci
116e1051a39Sopenharmony_ci/*-
117e1051a39Sopenharmony_ci * This functions computes a single point multiplication over the EC group,
118e1051a39Sopenharmony_ci * using, at a high level, a Montgomery ladder with conditional swaps, with
119e1051a39Sopenharmony_ci * various timing attack defenses.
120e1051a39Sopenharmony_ci *
121e1051a39Sopenharmony_ci * It performs either a fixed point multiplication
122e1051a39Sopenharmony_ci *          (scalar * generator)
123e1051a39Sopenharmony_ci * when point is NULL, or a variable point multiplication
124e1051a39Sopenharmony_ci *          (scalar * point)
125e1051a39Sopenharmony_ci * when point is not NULL.
126e1051a39Sopenharmony_ci *
127e1051a39Sopenharmony_ci * `scalar` cannot be NULL and should be in the range [0,n) otherwise all
128e1051a39Sopenharmony_ci * constant time bets are off (where n is the cardinality of the EC group).
129e1051a39Sopenharmony_ci *
130e1051a39Sopenharmony_ci * This function expects `group->order` and `group->cardinality` to be well
131e1051a39Sopenharmony_ci * defined and non-zero: it fails with an error code otherwise.
132e1051a39Sopenharmony_ci *
133e1051a39Sopenharmony_ci * NB: This says nothing about the constant-timeness of the ladder step
134e1051a39Sopenharmony_ci * implementation (i.e., the default implementation is based on EC_POINT_add and
135e1051a39Sopenharmony_ci * EC_POINT_dbl, which of course are not constant time themselves) or the
136e1051a39Sopenharmony_ci * underlying multiprecision arithmetic.
137e1051a39Sopenharmony_ci *
138e1051a39Sopenharmony_ci * The product is stored in `r`.
139e1051a39Sopenharmony_ci *
140e1051a39Sopenharmony_ci * This is an internal function: callers are in charge of ensuring that the
141e1051a39Sopenharmony_ci * input parameters `group`, `r`, `scalar` and `ctx` are not NULL.
142e1051a39Sopenharmony_ci *
143e1051a39Sopenharmony_ci * Returns 1 on success, 0 otherwise.
144e1051a39Sopenharmony_ci */
145e1051a39Sopenharmony_ciint ossl_ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
146e1051a39Sopenharmony_ci                              const BIGNUM *scalar, const EC_POINT *point,
147e1051a39Sopenharmony_ci                              BN_CTX *ctx)
148e1051a39Sopenharmony_ci{
149e1051a39Sopenharmony_ci    int i, cardinality_bits, group_top, kbit, pbit, Z_is_one;
150e1051a39Sopenharmony_ci    EC_POINT *p = NULL;
151e1051a39Sopenharmony_ci    EC_POINT *s = NULL;
152e1051a39Sopenharmony_ci    BIGNUM *k = NULL;
153e1051a39Sopenharmony_ci    BIGNUM *lambda = NULL;
154e1051a39Sopenharmony_ci    BIGNUM *cardinality = NULL;
155e1051a39Sopenharmony_ci    int ret = 0;
156e1051a39Sopenharmony_ci
157e1051a39Sopenharmony_ci    /* early exit if the input point is the point at infinity */
158e1051a39Sopenharmony_ci    if (point != NULL && EC_POINT_is_at_infinity(group, point))
159e1051a39Sopenharmony_ci        return EC_POINT_set_to_infinity(group, r);
160e1051a39Sopenharmony_ci
161e1051a39Sopenharmony_ci    if (BN_is_zero(group->order)) {
162e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_ORDER);
163e1051a39Sopenharmony_ci        return 0;
164e1051a39Sopenharmony_ci    }
165e1051a39Sopenharmony_ci    if (BN_is_zero(group->cofactor)) {
166e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_COFACTOR);
167e1051a39Sopenharmony_ci        return 0;
168e1051a39Sopenharmony_ci    }
169e1051a39Sopenharmony_ci
170e1051a39Sopenharmony_ci    BN_CTX_start(ctx);
171e1051a39Sopenharmony_ci
172e1051a39Sopenharmony_ci    if (((p = EC_POINT_new(group)) == NULL)
173e1051a39Sopenharmony_ci        || ((s = EC_POINT_new(group)) == NULL)) {
174e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
175e1051a39Sopenharmony_ci        goto err;
176e1051a39Sopenharmony_ci    }
177e1051a39Sopenharmony_ci
178e1051a39Sopenharmony_ci    if (point == NULL) {
179e1051a39Sopenharmony_ci        if (!EC_POINT_copy(p, group->generator)) {
180e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
181e1051a39Sopenharmony_ci            goto err;
182e1051a39Sopenharmony_ci        }
183e1051a39Sopenharmony_ci    } else {
184e1051a39Sopenharmony_ci        if (!EC_POINT_copy(p, point)) {
185e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
186e1051a39Sopenharmony_ci            goto err;
187e1051a39Sopenharmony_ci        }
188e1051a39Sopenharmony_ci    }
189e1051a39Sopenharmony_ci
190e1051a39Sopenharmony_ci    EC_POINT_BN_set_flags(p, BN_FLG_CONSTTIME);
191e1051a39Sopenharmony_ci    EC_POINT_BN_set_flags(r, BN_FLG_CONSTTIME);
192e1051a39Sopenharmony_ci    EC_POINT_BN_set_flags(s, BN_FLG_CONSTTIME);
193e1051a39Sopenharmony_ci
194e1051a39Sopenharmony_ci    cardinality = BN_CTX_get(ctx);
195e1051a39Sopenharmony_ci    lambda = BN_CTX_get(ctx);
196e1051a39Sopenharmony_ci    k = BN_CTX_get(ctx);
197e1051a39Sopenharmony_ci    if (k == NULL) {
198e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
199e1051a39Sopenharmony_ci        goto err;
200e1051a39Sopenharmony_ci    }
201e1051a39Sopenharmony_ci
202e1051a39Sopenharmony_ci    if (!BN_mul(cardinality, group->order, group->cofactor, ctx)) {
203e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
204e1051a39Sopenharmony_ci        goto err;
205e1051a39Sopenharmony_ci    }
206e1051a39Sopenharmony_ci
207e1051a39Sopenharmony_ci    /*
208e1051a39Sopenharmony_ci     * Group cardinalities are often on a word boundary.
209e1051a39Sopenharmony_ci     * So when we pad the scalar, some timing diff might
210e1051a39Sopenharmony_ci     * pop if it needs to be expanded due to carries.
211e1051a39Sopenharmony_ci     * So expand ahead of time.
212e1051a39Sopenharmony_ci     */
213e1051a39Sopenharmony_ci    cardinality_bits = BN_num_bits(cardinality);
214e1051a39Sopenharmony_ci    group_top = bn_get_top(cardinality);
215e1051a39Sopenharmony_ci    if ((bn_wexpand(k, group_top + 2) == NULL)
216e1051a39Sopenharmony_ci        || (bn_wexpand(lambda, group_top + 2) == NULL)) {
217e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
218e1051a39Sopenharmony_ci        goto err;
219e1051a39Sopenharmony_ci    }
220e1051a39Sopenharmony_ci
221e1051a39Sopenharmony_ci    if (!BN_copy(k, scalar)) {
222e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
223e1051a39Sopenharmony_ci        goto err;
224e1051a39Sopenharmony_ci    }
225e1051a39Sopenharmony_ci
226e1051a39Sopenharmony_ci    BN_set_flags(k, BN_FLG_CONSTTIME);
227e1051a39Sopenharmony_ci
228e1051a39Sopenharmony_ci    if ((BN_num_bits(k) > cardinality_bits) || (BN_is_negative(k))) {
229e1051a39Sopenharmony_ci        /*-
230e1051a39Sopenharmony_ci         * this is an unusual input, and we don't guarantee
231e1051a39Sopenharmony_ci         * constant-timeness
232e1051a39Sopenharmony_ci         */
233e1051a39Sopenharmony_ci        if (!BN_nnmod(k, k, cardinality, ctx)) {
234e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
235e1051a39Sopenharmony_ci            goto err;
236e1051a39Sopenharmony_ci        }
237e1051a39Sopenharmony_ci    }
238e1051a39Sopenharmony_ci
239e1051a39Sopenharmony_ci    if (!BN_add(lambda, k, cardinality)) {
240e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
241e1051a39Sopenharmony_ci        goto err;
242e1051a39Sopenharmony_ci    }
243e1051a39Sopenharmony_ci    BN_set_flags(lambda, BN_FLG_CONSTTIME);
244e1051a39Sopenharmony_ci    if (!BN_add(k, lambda, cardinality)) {
245e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
246e1051a39Sopenharmony_ci        goto err;
247e1051a39Sopenharmony_ci    }
248e1051a39Sopenharmony_ci    /*
249e1051a39Sopenharmony_ci     * lambda := scalar + cardinality
250e1051a39Sopenharmony_ci     * k := scalar + 2*cardinality
251e1051a39Sopenharmony_ci     */
252e1051a39Sopenharmony_ci    kbit = BN_is_bit_set(lambda, cardinality_bits);
253e1051a39Sopenharmony_ci    BN_consttime_swap(kbit, k, lambda, group_top + 2);
254e1051a39Sopenharmony_ci
255e1051a39Sopenharmony_ci    group_top = bn_get_top(group->field);
256e1051a39Sopenharmony_ci    if ((bn_wexpand(s->X, group_top) == NULL)
257e1051a39Sopenharmony_ci        || (bn_wexpand(s->Y, group_top) == NULL)
258e1051a39Sopenharmony_ci        || (bn_wexpand(s->Z, group_top) == NULL)
259e1051a39Sopenharmony_ci        || (bn_wexpand(r->X, group_top) == NULL)
260e1051a39Sopenharmony_ci        || (bn_wexpand(r->Y, group_top) == NULL)
261e1051a39Sopenharmony_ci        || (bn_wexpand(r->Z, group_top) == NULL)
262e1051a39Sopenharmony_ci        || (bn_wexpand(p->X, group_top) == NULL)
263e1051a39Sopenharmony_ci        || (bn_wexpand(p->Y, group_top) == NULL)
264e1051a39Sopenharmony_ci        || (bn_wexpand(p->Z, group_top) == NULL)) {
265e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
266e1051a39Sopenharmony_ci        goto err;
267e1051a39Sopenharmony_ci    }
268e1051a39Sopenharmony_ci
269e1051a39Sopenharmony_ci    /* ensure input point is in affine coords for ladder step efficiency */
270e1051a39Sopenharmony_ci    if (!p->Z_is_one && (group->meth->make_affine == NULL
271e1051a39Sopenharmony_ci                         || !group->meth->make_affine(group, p, ctx))) {
272e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
273e1051a39Sopenharmony_ci            goto err;
274e1051a39Sopenharmony_ci    }
275e1051a39Sopenharmony_ci
276e1051a39Sopenharmony_ci    /* Initialize the Montgomery ladder */
277e1051a39Sopenharmony_ci    if (!ec_point_ladder_pre(group, r, s, p, ctx)) {
278e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_LADDER_PRE_FAILURE);
279e1051a39Sopenharmony_ci        goto err;
280e1051a39Sopenharmony_ci    }
281e1051a39Sopenharmony_ci
282e1051a39Sopenharmony_ci    /* top bit is a 1, in a fixed pos */
283e1051a39Sopenharmony_ci    pbit = 1;
284e1051a39Sopenharmony_ci
285e1051a39Sopenharmony_ci#define EC_POINT_CSWAP(c, a, b, w, t) do {         \
286e1051a39Sopenharmony_ci        BN_consttime_swap(c, (a)->X, (b)->X, w);   \
287e1051a39Sopenharmony_ci        BN_consttime_swap(c, (a)->Y, (b)->Y, w);   \
288e1051a39Sopenharmony_ci        BN_consttime_swap(c, (a)->Z, (b)->Z, w);   \
289e1051a39Sopenharmony_ci        t = ((a)->Z_is_one ^ (b)->Z_is_one) & (c); \
290e1051a39Sopenharmony_ci        (a)->Z_is_one ^= (t);                      \
291e1051a39Sopenharmony_ci        (b)->Z_is_one ^= (t);                      \
292e1051a39Sopenharmony_ci} while(0)
293e1051a39Sopenharmony_ci
294e1051a39Sopenharmony_ci    /*-
295e1051a39Sopenharmony_ci     * The ladder step, with branches, is
296e1051a39Sopenharmony_ci     *
297e1051a39Sopenharmony_ci     * k[i] == 0: S = add(R, S), R = dbl(R)
298e1051a39Sopenharmony_ci     * k[i] == 1: R = add(S, R), S = dbl(S)
299e1051a39Sopenharmony_ci     *
300e1051a39Sopenharmony_ci     * Swapping R, S conditionally on k[i] leaves you with state
301e1051a39Sopenharmony_ci     *
302e1051a39Sopenharmony_ci     * k[i] == 0: T, U = R, S
303e1051a39Sopenharmony_ci     * k[i] == 1: T, U = S, R
304e1051a39Sopenharmony_ci     *
305e1051a39Sopenharmony_ci     * Then perform the ECC ops.
306e1051a39Sopenharmony_ci     *
307e1051a39Sopenharmony_ci     * U = add(T, U)
308e1051a39Sopenharmony_ci     * T = dbl(T)
309e1051a39Sopenharmony_ci     *
310e1051a39Sopenharmony_ci     * Which leaves you with state
311e1051a39Sopenharmony_ci     *
312e1051a39Sopenharmony_ci     * k[i] == 0: U = add(R, S), T = dbl(R)
313e1051a39Sopenharmony_ci     * k[i] == 1: U = add(S, R), T = dbl(S)
314e1051a39Sopenharmony_ci     *
315e1051a39Sopenharmony_ci     * Swapping T, U conditionally on k[i] leaves you with state
316e1051a39Sopenharmony_ci     *
317e1051a39Sopenharmony_ci     * k[i] == 0: R, S = T, U
318e1051a39Sopenharmony_ci     * k[i] == 1: R, S = U, T
319e1051a39Sopenharmony_ci     *
320e1051a39Sopenharmony_ci     * Which leaves you with state
321e1051a39Sopenharmony_ci     *
322e1051a39Sopenharmony_ci     * k[i] == 0: S = add(R, S), R = dbl(R)
323e1051a39Sopenharmony_ci     * k[i] == 1: R = add(S, R), S = dbl(S)
324e1051a39Sopenharmony_ci     *
325e1051a39Sopenharmony_ci     * So we get the same logic, but instead of a branch it's a
326e1051a39Sopenharmony_ci     * conditional swap, followed by ECC ops, then another conditional swap.
327e1051a39Sopenharmony_ci     *
328e1051a39Sopenharmony_ci     * Optimization: The end of iteration i and start of i-1 looks like
329e1051a39Sopenharmony_ci     *
330e1051a39Sopenharmony_ci     * ...
331e1051a39Sopenharmony_ci     * CSWAP(k[i], R, S)
332e1051a39Sopenharmony_ci     * ECC
333e1051a39Sopenharmony_ci     * CSWAP(k[i], R, S)
334e1051a39Sopenharmony_ci     * (next iteration)
335e1051a39Sopenharmony_ci     * CSWAP(k[i-1], R, S)
336e1051a39Sopenharmony_ci     * ECC
337e1051a39Sopenharmony_ci     * CSWAP(k[i-1], R, S)
338e1051a39Sopenharmony_ci     * ...
339e1051a39Sopenharmony_ci     *
340e1051a39Sopenharmony_ci     * So instead of two contiguous swaps, you can merge the condition
341e1051a39Sopenharmony_ci     * bits and do a single swap.
342e1051a39Sopenharmony_ci     *
343e1051a39Sopenharmony_ci     * k[i]   k[i-1]    Outcome
344e1051a39Sopenharmony_ci     * 0      0         No Swap
345e1051a39Sopenharmony_ci     * 0      1         Swap
346e1051a39Sopenharmony_ci     * 1      0         Swap
347e1051a39Sopenharmony_ci     * 1      1         No Swap
348e1051a39Sopenharmony_ci     *
349e1051a39Sopenharmony_ci     * This is XOR. pbit tracks the previous bit of k.
350e1051a39Sopenharmony_ci     */
351e1051a39Sopenharmony_ci
352e1051a39Sopenharmony_ci    for (i = cardinality_bits - 1; i >= 0; i--) {
353e1051a39Sopenharmony_ci        kbit = BN_is_bit_set(k, i) ^ pbit;
354e1051a39Sopenharmony_ci        EC_POINT_CSWAP(kbit, r, s, group_top, Z_is_one);
355e1051a39Sopenharmony_ci
356e1051a39Sopenharmony_ci        /* Perform a single step of the Montgomery ladder */
357e1051a39Sopenharmony_ci        if (!ec_point_ladder_step(group, r, s, p, ctx)) {
358e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, EC_R_LADDER_STEP_FAILURE);
359e1051a39Sopenharmony_ci            goto err;
360e1051a39Sopenharmony_ci        }
361e1051a39Sopenharmony_ci        /*
362e1051a39Sopenharmony_ci         * pbit logic merges this cswap with that of the
363e1051a39Sopenharmony_ci         * next iteration
364e1051a39Sopenharmony_ci         */
365e1051a39Sopenharmony_ci        pbit ^= kbit;
366e1051a39Sopenharmony_ci    }
367e1051a39Sopenharmony_ci    /* one final cswap to move the right value into r */
368e1051a39Sopenharmony_ci    EC_POINT_CSWAP(pbit, r, s, group_top, Z_is_one);
369e1051a39Sopenharmony_ci#undef EC_POINT_CSWAP
370e1051a39Sopenharmony_ci
371e1051a39Sopenharmony_ci    /* Finalize ladder (and recover full point coordinates) */
372e1051a39Sopenharmony_ci    if (!ec_point_ladder_post(group, r, s, p, ctx)) {
373e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_LADDER_POST_FAILURE);
374e1051a39Sopenharmony_ci        goto err;
375e1051a39Sopenharmony_ci    }
376e1051a39Sopenharmony_ci
377e1051a39Sopenharmony_ci    ret = 1;
378e1051a39Sopenharmony_ci
379e1051a39Sopenharmony_ci err:
380e1051a39Sopenharmony_ci    EC_POINT_free(p);
381e1051a39Sopenharmony_ci    EC_POINT_clear_free(s);
382e1051a39Sopenharmony_ci    BN_CTX_end(ctx);
383e1051a39Sopenharmony_ci
384e1051a39Sopenharmony_ci    return ret;
385e1051a39Sopenharmony_ci}
386e1051a39Sopenharmony_ci
387e1051a39Sopenharmony_ci#undef EC_POINT_BN_set_flags
388e1051a39Sopenharmony_ci
389e1051a39Sopenharmony_ci/*
390e1051a39Sopenharmony_ci * Table could be optimised for the wNAF-based implementation,
391e1051a39Sopenharmony_ci * sometimes smaller windows will give better performance (thus the
392e1051a39Sopenharmony_ci * boundaries should be increased)
393e1051a39Sopenharmony_ci */
394e1051a39Sopenharmony_ci#define EC_window_bits_for_scalar_size(b) \
395e1051a39Sopenharmony_ci                ((size_t) \
396e1051a39Sopenharmony_ci                 ((b) >= 2000 ? 6 : \
397e1051a39Sopenharmony_ci                  (b) >=  800 ? 5 : \
398e1051a39Sopenharmony_ci                  (b) >=  300 ? 4 : \
399e1051a39Sopenharmony_ci                  (b) >=   70 ? 3 : \
400e1051a39Sopenharmony_ci                  (b) >=   20 ? 2 : \
401e1051a39Sopenharmony_ci                  1))
402e1051a39Sopenharmony_ci
403e1051a39Sopenharmony_ci/*-
404e1051a39Sopenharmony_ci * Compute
405e1051a39Sopenharmony_ci *      \sum scalars[i]*points[i],
406e1051a39Sopenharmony_ci * also including
407e1051a39Sopenharmony_ci *      scalar*generator
408e1051a39Sopenharmony_ci * in the addition if scalar != NULL
409e1051a39Sopenharmony_ci */
410e1051a39Sopenharmony_ciint ossl_ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
411e1051a39Sopenharmony_ci                     size_t num, const EC_POINT *points[],
412e1051a39Sopenharmony_ci                     const BIGNUM *scalars[], BN_CTX *ctx)
413e1051a39Sopenharmony_ci{
414e1051a39Sopenharmony_ci    const EC_POINT *generator = NULL;
415e1051a39Sopenharmony_ci    EC_POINT *tmp = NULL;
416e1051a39Sopenharmony_ci    size_t totalnum;
417e1051a39Sopenharmony_ci    size_t blocksize = 0, numblocks = 0; /* for wNAF splitting */
418e1051a39Sopenharmony_ci    size_t pre_points_per_block = 0;
419e1051a39Sopenharmony_ci    size_t i, j;
420e1051a39Sopenharmony_ci    int k;
421e1051a39Sopenharmony_ci    int r_is_inverted = 0;
422e1051a39Sopenharmony_ci    int r_is_at_infinity = 1;
423e1051a39Sopenharmony_ci    size_t *wsize = NULL;       /* individual window sizes */
424e1051a39Sopenharmony_ci    signed char **wNAF = NULL;  /* individual wNAFs */
425e1051a39Sopenharmony_ci    size_t *wNAF_len = NULL;
426e1051a39Sopenharmony_ci    size_t max_len = 0;
427e1051a39Sopenharmony_ci    size_t num_val;
428e1051a39Sopenharmony_ci    EC_POINT **val = NULL;      /* precomputation */
429e1051a39Sopenharmony_ci    EC_POINT **v;
430e1051a39Sopenharmony_ci    EC_POINT ***val_sub = NULL; /* pointers to sub-arrays of 'val' or
431e1051a39Sopenharmony_ci                                 * 'pre_comp->points' */
432e1051a39Sopenharmony_ci    const EC_PRE_COMP *pre_comp = NULL;
433e1051a39Sopenharmony_ci    int num_scalar = 0;         /* flag: will be set to 1 if 'scalar' must be
434e1051a39Sopenharmony_ci                                 * treated like other scalars, i.e.
435e1051a39Sopenharmony_ci                                 * precomputation is not available */
436e1051a39Sopenharmony_ci    int ret = 0;
437e1051a39Sopenharmony_ci
438e1051a39Sopenharmony_ci    if (!BN_is_zero(group->order) && !BN_is_zero(group->cofactor)) {
439e1051a39Sopenharmony_ci        /*-
440e1051a39Sopenharmony_ci         * Handle the common cases where the scalar is secret, enforcing a
441e1051a39Sopenharmony_ci         * scalar multiplication implementation based on a Montgomery ladder,
442e1051a39Sopenharmony_ci         * with various timing attack defenses.
443e1051a39Sopenharmony_ci         */
444e1051a39Sopenharmony_ci        if ((scalar != group->order) && (scalar != NULL) && (num == 0)) {
445e1051a39Sopenharmony_ci            /*-
446e1051a39Sopenharmony_ci             * In this case we want to compute scalar * GeneratorPoint: this
447e1051a39Sopenharmony_ci             * codepath is reached most prominently by (ephemeral) key
448e1051a39Sopenharmony_ci             * generation of EC cryptosystems (i.e. ECDSA keygen and sign setup,
449e1051a39Sopenharmony_ci             * ECDH keygen/first half), where the scalar is always secret. This
450e1051a39Sopenharmony_ci             * is why we ignore if BN_FLG_CONSTTIME is actually set and we
451e1051a39Sopenharmony_ci             * always call the ladder version.
452e1051a39Sopenharmony_ci             */
453e1051a39Sopenharmony_ci            return ossl_ec_scalar_mul_ladder(group, r, scalar, NULL, ctx);
454e1051a39Sopenharmony_ci        }
455e1051a39Sopenharmony_ci        if ((scalar == NULL) && (num == 1) && (scalars[0] != group->order)) {
456e1051a39Sopenharmony_ci            /*-
457e1051a39Sopenharmony_ci             * In this case we want to compute scalar * VariablePoint: this
458e1051a39Sopenharmony_ci             * codepath is reached most prominently by the second half of ECDH,
459e1051a39Sopenharmony_ci             * where the secret scalar is multiplied by the peer's public point.
460e1051a39Sopenharmony_ci             * To protect the secret scalar, we ignore if BN_FLG_CONSTTIME is
461e1051a39Sopenharmony_ci             * actually set and we always call the ladder version.
462e1051a39Sopenharmony_ci             */
463e1051a39Sopenharmony_ci            return ossl_ec_scalar_mul_ladder(group, r, scalars[0], points[0],
464e1051a39Sopenharmony_ci                                             ctx);
465e1051a39Sopenharmony_ci        }
466e1051a39Sopenharmony_ci    }
467e1051a39Sopenharmony_ci
468e1051a39Sopenharmony_ci    if (scalar != NULL) {
469e1051a39Sopenharmony_ci        generator = EC_GROUP_get0_generator(group);
470e1051a39Sopenharmony_ci        if (generator == NULL) {
471e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, EC_R_UNDEFINED_GENERATOR);
472e1051a39Sopenharmony_ci            goto err;
473e1051a39Sopenharmony_ci        }
474e1051a39Sopenharmony_ci
475e1051a39Sopenharmony_ci        /* look if we can use precomputed multiples of generator */
476e1051a39Sopenharmony_ci
477e1051a39Sopenharmony_ci        pre_comp = group->pre_comp.ec;
478e1051a39Sopenharmony_ci        if (pre_comp && pre_comp->numblocks
479e1051a39Sopenharmony_ci            && (EC_POINT_cmp(group, generator, pre_comp->points[0], ctx) ==
480e1051a39Sopenharmony_ci                0)) {
481e1051a39Sopenharmony_ci            blocksize = pre_comp->blocksize;
482e1051a39Sopenharmony_ci
483e1051a39Sopenharmony_ci            /*
484e1051a39Sopenharmony_ci             * determine maximum number of blocks that wNAF splitting may
485e1051a39Sopenharmony_ci             * yield (NB: maximum wNAF length is bit length plus one)
486e1051a39Sopenharmony_ci             */
487e1051a39Sopenharmony_ci            numblocks = (BN_num_bits(scalar) / blocksize) + 1;
488e1051a39Sopenharmony_ci
489e1051a39Sopenharmony_ci            /*
490e1051a39Sopenharmony_ci             * we cannot use more blocks than we have precomputation for
491e1051a39Sopenharmony_ci             */
492e1051a39Sopenharmony_ci            if (numblocks > pre_comp->numblocks)
493e1051a39Sopenharmony_ci                numblocks = pre_comp->numblocks;
494e1051a39Sopenharmony_ci
495e1051a39Sopenharmony_ci            pre_points_per_block = (size_t)1 << (pre_comp->w - 1);
496e1051a39Sopenharmony_ci
497e1051a39Sopenharmony_ci            /* check that pre_comp looks sane */
498e1051a39Sopenharmony_ci            if (pre_comp->num != (pre_comp->numblocks * pre_points_per_block)) {
499e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
500e1051a39Sopenharmony_ci                goto err;
501e1051a39Sopenharmony_ci            }
502e1051a39Sopenharmony_ci        } else {
503e1051a39Sopenharmony_ci            /* can't use precomputation */
504e1051a39Sopenharmony_ci            pre_comp = NULL;
505e1051a39Sopenharmony_ci            numblocks = 1;
506e1051a39Sopenharmony_ci            num_scalar = 1;     /* treat 'scalar' like 'num'-th element of
507e1051a39Sopenharmony_ci                                 * 'scalars' */
508e1051a39Sopenharmony_ci        }
509e1051a39Sopenharmony_ci    }
510e1051a39Sopenharmony_ci
511e1051a39Sopenharmony_ci    totalnum = num + numblocks;
512e1051a39Sopenharmony_ci
513e1051a39Sopenharmony_ci    wsize = OPENSSL_malloc(totalnum * sizeof(wsize[0]));
514e1051a39Sopenharmony_ci    wNAF_len = OPENSSL_malloc(totalnum * sizeof(wNAF_len[0]));
515e1051a39Sopenharmony_ci    /* include space for pivot */
516e1051a39Sopenharmony_ci    wNAF = OPENSSL_malloc((totalnum + 1) * sizeof(wNAF[0]));
517e1051a39Sopenharmony_ci    val_sub = OPENSSL_malloc(totalnum * sizeof(val_sub[0]));
518e1051a39Sopenharmony_ci
519e1051a39Sopenharmony_ci    /* Ensure wNAF is initialised in case we end up going to err */
520e1051a39Sopenharmony_ci    if (wNAF != NULL)
521e1051a39Sopenharmony_ci        wNAF[0] = NULL;         /* preliminary pivot */
522e1051a39Sopenharmony_ci
523e1051a39Sopenharmony_ci    if (wsize == NULL || wNAF_len == NULL || wNAF == NULL || val_sub == NULL) {
524e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
525e1051a39Sopenharmony_ci        goto err;
526e1051a39Sopenharmony_ci    }
527e1051a39Sopenharmony_ci
528e1051a39Sopenharmony_ci    /*
529e1051a39Sopenharmony_ci     * num_val will be the total number of temporarily precomputed points
530e1051a39Sopenharmony_ci     */
531e1051a39Sopenharmony_ci    num_val = 0;
532e1051a39Sopenharmony_ci
533e1051a39Sopenharmony_ci    for (i = 0; i < num + num_scalar; i++) {
534e1051a39Sopenharmony_ci        size_t bits;
535e1051a39Sopenharmony_ci
536e1051a39Sopenharmony_ci        bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(scalar);
537e1051a39Sopenharmony_ci        wsize[i] = EC_window_bits_for_scalar_size(bits);
538e1051a39Sopenharmony_ci        num_val += (size_t)1 << (wsize[i] - 1);
539e1051a39Sopenharmony_ci        wNAF[i + 1] = NULL;     /* make sure we always have a pivot */
540e1051a39Sopenharmony_ci        wNAF[i] =
541e1051a39Sopenharmony_ci            bn_compute_wNAF((i < num ? scalars[i] : scalar), wsize[i],
542e1051a39Sopenharmony_ci                            &wNAF_len[i]);
543e1051a39Sopenharmony_ci        if (wNAF[i] == NULL)
544e1051a39Sopenharmony_ci            goto err;
545e1051a39Sopenharmony_ci        if (wNAF_len[i] > max_len)
546e1051a39Sopenharmony_ci            max_len = wNAF_len[i];
547e1051a39Sopenharmony_ci    }
548e1051a39Sopenharmony_ci
549e1051a39Sopenharmony_ci    if (numblocks) {
550e1051a39Sopenharmony_ci        /* we go here iff scalar != NULL */
551e1051a39Sopenharmony_ci
552e1051a39Sopenharmony_ci        if (pre_comp == NULL) {
553e1051a39Sopenharmony_ci            if (num_scalar != 1) {
554e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
555e1051a39Sopenharmony_ci                goto err;
556e1051a39Sopenharmony_ci            }
557e1051a39Sopenharmony_ci            /* we have already generated a wNAF for 'scalar' */
558e1051a39Sopenharmony_ci        } else {
559e1051a39Sopenharmony_ci            signed char *tmp_wNAF = NULL;
560e1051a39Sopenharmony_ci            size_t tmp_len = 0;
561e1051a39Sopenharmony_ci
562e1051a39Sopenharmony_ci            if (num_scalar != 0) {
563e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
564e1051a39Sopenharmony_ci                goto err;
565e1051a39Sopenharmony_ci            }
566e1051a39Sopenharmony_ci
567e1051a39Sopenharmony_ci            /*
568e1051a39Sopenharmony_ci             * use the window size for which we have precomputation
569e1051a39Sopenharmony_ci             */
570e1051a39Sopenharmony_ci            wsize[num] = pre_comp->w;
571e1051a39Sopenharmony_ci            tmp_wNAF = bn_compute_wNAF(scalar, wsize[num], &tmp_len);
572e1051a39Sopenharmony_ci            if (!tmp_wNAF)
573e1051a39Sopenharmony_ci                goto err;
574e1051a39Sopenharmony_ci
575e1051a39Sopenharmony_ci            if (tmp_len <= max_len) {
576e1051a39Sopenharmony_ci                /*
577e1051a39Sopenharmony_ci                 * One of the other wNAFs is at least as long as the wNAF
578e1051a39Sopenharmony_ci                 * belonging to the generator, so wNAF splitting will not buy
579e1051a39Sopenharmony_ci                 * us anything.
580e1051a39Sopenharmony_ci                 */
581e1051a39Sopenharmony_ci
582e1051a39Sopenharmony_ci                numblocks = 1;
583e1051a39Sopenharmony_ci                totalnum = num + 1; /* don't use wNAF splitting */
584e1051a39Sopenharmony_ci                wNAF[num] = tmp_wNAF;
585e1051a39Sopenharmony_ci                wNAF[num + 1] = NULL;
586e1051a39Sopenharmony_ci                wNAF_len[num] = tmp_len;
587e1051a39Sopenharmony_ci                /*
588e1051a39Sopenharmony_ci                 * pre_comp->points starts with the points that we need here:
589e1051a39Sopenharmony_ci                 */
590e1051a39Sopenharmony_ci                val_sub[num] = pre_comp->points;
591e1051a39Sopenharmony_ci            } else {
592e1051a39Sopenharmony_ci                /*
593e1051a39Sopenharmony_ci                 * don't include tmp_wNAF directly into wNAF array - use wNAF
594e1051a39Sopenharmony_ci                 * splitting and include the blocks
595e1051a39Sopenharmony_ci                 */
596e1051a39Sopenharmony_ci
597e1051a39Sopenharmony_ci                signed char *pp;
598e1051a39Sopenharmony_ci                EC_POINT **tmp_points;
599e1051a39Sopenharmony_ci
600e1051a39Sopenharmony_ci                if (tmp_len < numblocks * blocksize) {
601e1051a39Sopenharmony_ci                    /*
602e1051a39Sopenharmony_ci                     * possibly we can do with fewer blocks than estimated
603e1051a39Sopenharmony_ci                     */
604e1051a39Sopenharmony_ci                    numblocks = (tmp_len + blocksize - 1) / blocksize;
605e1051a39Sopenharmony_ci                    if (numblocks > pre_comp->numblocks) {
606e1051a39Sopenharmony_ci                        ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
607e1051a39Sopenharmony_ci                        OPENSSL_free(tmp_wNAF);
608e1051a39Sopenharmony_ci                        goto err;
609e1051a39Sopenharmony_ci                    }
610e1051a39Sopenharmony_ci                    totalnum = num + numblocks;
611e1051a39Sopenharmony_ci                }
612e1051a39Sopenharmony_ci
613e1051a39Sopenharmony_ci                /* split wNAF in 'numblocks' parts */
614e1051a39Sopenharmony_ci                pp = tmp_wNAF;
615e1051a39Sopenharmony_ci                tmp_points = pre_comp->points;
616e1051a39Sopenharmony_ci
617e1051a39Sopenharmony_ci                for (i = num; i < totalnum; i++) {
618e1051a39Sopenharmony_ci                    if (i < totalnum - 1) {
619e1051a39Sopenharmony_ci                        wNAF_len[i] = blocksize;
620e1051a39Sopenharmony_ci                        if (tmp_len < blocksize) {
621e1051a39Sopenharmony_ci                            ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
622e1051a39Sopenharmony_ci                            OPENSSL_free(tmp_wNAF);
623e1051a39Sopenharmony_ci                            goto err;
624e1051a39Sopenharmony_ci                        }
625e1051a39Sopenharmony_ci                        tmp_len -= blocksize;
626e1051a39Sopenharmony_ci                    } else
627e1051a39Sopenharmony_ci                        /*
628e1051a39Sopenharmony_ci                         * last block gets whatever is left (this could be
629e1051a39Sopenharmony_ci                         * more or less than 'blocksize'!)
630e1051a39Sopenharmony_ci                         */
631e1051a39Sopenharmony_ci                        wNAF_len[i] = tmp_len;
632e1051a39Sopenharmony_ci
633e1051a39Sopenharmony_ci                    wNAF[i + 1] = NULL;
634e1051a39Sopenharmony_ci                    wNAF[i] = OPENSSL_malloc(wNAF_len[i]);
635e1051a39Sopenharmony_ci                    if (wNAF[i] == NULL) {
636e1051a39Sopenharmony_ci                        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
637e1051a39Sopenharmony_ci                        OPENSSL_free(tmp_wNAF);
638e1051a39Sopenharmony_ci                        goto err;
639e1051a39Sopenharmony_ci                    }
640e1051a39Sopenharmony_ci                    memcpy(wNAF[i], pp, wNAF_len[i]);
641e1051a39Sopenharmony_ci                    if (wNAF_len[i] > max_len)
642e1051a39Sopenharmony_ci                        max_len = wNAF_len[i];
643e1051a39Sopenharmony_ci
644e1051a39Sopenharmony_ci                    if (*tmp_points == NULL) {
645e1051a39Sopenharmony_ci                        ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
646e1051a39Sopenharmony_ci                        OPENSSL_free(tmp_wNAF);
647e1051a39Sopenharmony_ci                        goto err;
648e1051a39Sopenharmony_ci                    }
649e1051a39Sopenharmony_ci                    val_sub[i] = tmp_points;
650e1051a39Sopenharmony_ci                    tmp_points += pre_points_per_block;
651e1051a39Sopenharmony_ci                    pp += blocksize;
652e1051a39Sopenharmony_ci                }
653e1051a39Sopenharmony_ci                OPENSSL_free(tmp_wNAF);
654e1051a39Sopenharmony_ci            }
655e1051a39Sopenharmony_ci        }
656e1051a39Sopenharmony_ci    }
657e1051a39Sopenharmony_ci
658e1051a39Sopenharmony_ci    /*
659e1051a39Sopenharmony_ci     * All points we precompute now go into a single array 'val'.
660e1051a39Sopenharmony_ci     * 'val_sub[i]' is a pointer to the subarray for the i-th point, or to a
661e1051a39Sopenharmony_ci     * subarray of 'pre_comp->points' if we already have precomputation.
662e1051a39Sopenharmony_ci     */
663e1051a39Sopenharmony_ci    val = OPENSSL_malloc((num_val + 1) * sizeof(val[0]));
664e1051a39Sopenharmony_ci    if (val == NULL) {
665e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
666e1051a39Sopenharmony_ci        goto err;
667e1051a39Sopenharmony_ci    }
668e1051a39Sopenharmony_ci    val[num_val] = NULL;        /* pivot element */
669e1051a39Sopenharmony_ci
670e1051a39Sopenharmony_ci    /* allocate points for precomputation */
671e1051a39Sopenharmony_ci    v = val;
672e1051a39Sopenharmony_ci    for (i = 0; i < num + num_scalar; i++) {
673e1051a39Sopenharmony_ci        val_sub[i] = v;
674e1051a39Sopenharmony_ci        for (j = 0; j < ((size_t)1 << (wsize[i] - 1)); j++) {
675e1051a39Sopenharmony_ci            *v = EC_POINT_new(group);
676e1051a39Sopenharmony_ci            if (*v == NULL)
677e1051a39Sopenharmony_ci                goto err;
678e1051a39Sopenharmony_ci            v++;
679e1051a39Sopenharmony_ci        }
680e1051a39Sopenharmony_ci    }
681e1051a39Sopenharmony_ci    if (!(v == val + num_val)) {
682e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
683e1051a39Sopenharmony_ci        goto err;
684e1051a39Sopenharmony_ci    }
685e1051a39Sopenharmony_ci
686e1051a39Sopenharmony_ci    if ((tmp = EC_POINT_new(group)) == NULL)
687e1051a39Sopenharmony_ci        goto err;
688e1051a39Sopenharmony_ci
689e1051a39Sopenharmony_ci    /*-
690e1051a39Sopenharmony_ci     * prepare precomputed values:
691e1051a39Sopenharmony_ci     *    val_sub[i][0] :=     points[i]
692e1051a39Sopenharmony_ci     *    val_sub[i][1] := 3 * points[i]
693e1051a39Sopenharmony_ci     *    val_sub[i][2] := 5 * points[i]
694e1051a39Sopenharmony_ci     *    ...
695e1051a39Sopenharmony_ci     */
696e1051a39Sopenharmony_ci    for (i = 0; i < num + num_scalar; i++) {
697e1051a39Sopenharmony_ci        if (i < num) {
698e1051a39Sopenharmony_ci            if (!EC_POINT_copy(val_sub[i][0], points[i]))
699e1051a39Sopenharmony_ci                goto err;
700e1051a39Sopenharmony_ci        } else {
701e1051a39Sopenharmony_ci            if (!EC_POINT_copy(val_sub[i][0], generator))
702e1051a39Sopenharmony_ci                goto err;
703e1051a39Sopenharmony_ci        }
704e1051a39Sopenharmony_ci
705e1051a39Sopenharmony_ci        if (wsize[i] > 1) {
706e1051a39Sopenharmony_ci            if (!EC_POINT_dbl(group, tmp, val_sub[i][0], ctx))
707e1051a39Sopenharmony_ci                goto err;
708e1051a39Sopenharmony_ci            for (j = 1; j < ((size_t)1 << (wsize[i] - 1)); j++) {
709e1051a39Sopenharmony_ci                if (!EC_POINT_add
710e1051a39Sopenharmony_ci                    (group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx))
711e1051a39Sopenharmony_ci                    goto err;
712e1051a39Sopenharmony_ci            }
713e1051a39Sopenharmony_ci        }
714e1051a39Sopenharmony_ci    }
715e1051a39Sopenharmony_ci
716e1051a39Sopenharmony_ci    if (group->meth->points_make_affine == NULL
717e1051a39Sopenharmony_ci        || !group->meth->points_make_affine(group, num_val, val, ctx))
718e1051a39Sopenharmony_ci        goto err;
719e1051a39Sopenharmony_ci
720e1051a39Sopenharmony_ci    r_is_at_infinity = 1;
721e1051a39Sopenharmony_ci
722e1051a39Sopenharmony_ci    for (k = max_len - 1; k >= 0; k--) {
723e1051a39Sopenharmony_ci        if (!r_is_at_infinity) {
724e1051a39Sopenharmony_ci            if (!EC_POINT_dbl(group, r, r, ctx))
725e1051a39Sopenharmony_ci                goto err;
726e1051a39Sopenharmony_ci        }
727e1051a39Sopenharmony_ci
728e1051a39Sopenharmony_ci        for (i = 0; i < totalnum; i++) {
729e1051a39Sopenharmony_ci            if (wNAF_len[i] > (size_t)k) {
730e1051a39Sopenharmony_ci                int digit = wNAF[i][k];
731e1051a39Sopenharmony_ci                int is_neg;
732e1051a39Sopenharmony_ci
733e1051a39Sopenharmony_ci                if (digit) {
734e1051a39Sopenharmony_ci                    is_neg = digit < 0;
735e1051a39Sopenharmony_ci
736e1051a39Sopenharmony_ci                    if (is_neg)
737e1051a39Sopenharmony_ci                        digit = -digit;
738e1051a39Sopenharmony_ci
739e1051a39Sopenharmony_ci                    if (is_neg != r_is_inverted) {
740e1051a39Sopenharmony_ci                        if (!r_is_at_infinity) {
741e1051a39Sopenharmony_ci                            if (!EC_POINT_invert(group, r, ctx))
742e1051a39Sopenharmony_ci                                goto err;
743e1051a39Sopenharmony_ci                        }
744e1051a39Sopenharmony_ci                        r_is_inverted = !r_is_inverted;
745e1051a39Sopenharmony_ci                    }
746e1051a39Sopenharmony_ci
747e1051a39Sopenharmony_ci                    /* digit > 0 */
748e1051a39Sopenharmony_ci
749e1051a39Sopenharmony_ci                    if (r_is_at_infinity) {
750e1051a39Sopenharmony_ci                        if (!EC_POINT_copy(r, val_sub[i][digit >> 1]))
751e1051a39Sopenharmony_ci                            goto err;
752e1051a39Sopenharmony_ci
753e1051a39Sopenharmony_ci                        /*-
754e1051a39Sopenharmony_ci                         * Apply coordinate blinding for EC_POINT.
755e1051a39Sopenharmony_ci                         *
756e1051a39Sopenharmony_ci                         * The underlying EC_METHOD can optionally implement this function:
757e1051a39Sopenharmony_ci                         * ossl_ec_point_blind_coordinates() returns 0 in case of errors or 1 on
758e1051a39Sopenharmony_ci                         * success or if coordinate blinding is not implemented for this
759e1051a39Sopenharmony_ci                         * group.
760e1051a39Sopenharmony_ci                         */
761e1051a39Sopenharmony_ci                        if (!ossl_ec_point_blind_coordinates(group, r, ctx)) {
762e1051a39Sopenharmony_ci                            ERR_raise(ERR_LIB_EC, EC_R_POINT_COORDINATES_BLIND_FAILURE);
763e1051a39Sopenharmony_ci                            goto err;
764e1051a39Sopenharmony_ci                        }
765e1051a39Sopenharmony_ci
766e1051a39Sopenharmony_ci                        r_is_at_infinity = 0;
767e1051a39Sopenharmony_ci                    } else {
768e1051a39Sopenharmony_ci                        if (!EC_POINT_add
769e1051a39Sopenharmony_ci                            (group, r, r, val_sub[i][digit >> 1], ctx))
770e1051a39Sopenharmony_ci                            goto err;
771e1051a39Sopenharmony_ci                    }
772e1051a39Sopenharmony_ci                }
773e1051a39Sopenharmony_ci            }
774e1051a39Sopenharmony_ci        }
775e1051a39Sopenharmony_ci    }
776e1051a39Sopenharmony_ci
777e1051a39Sopenharmony_ci    if (r_is_at_infinity) {
778e1051a39Sopenharmony_ci        if (!EC_POINT_set_to_infinity(group, r))
779e1051a39Sopenharmony_ci            goto err;
780e1051a39Sopenharmony_ci    } else {
781e1051a39Sopenharmony_ci        if (r_is_inverted)
782e1051a39Sopenharmony_ci            if (!EC_POINT_invert(group, r, ctx))
783e1051a39Sopenharmony_ci                goto err;
784e1051a39Sopenharmony_ci    }
785e1051a39Sopenharmony_ci
786e1051a39Sopenharmony_ci    ret = 1;
787e1051a39Sopenharmony_ci
788e1051a39Sopenharmony_ci err:
789e1051a39Sopenharmony_ci    EC_POINT_free(tmp);
790e1051a39Sopenharmony_ci    OPENSSL_free(wsize);
791e1051a39Sopenharmony_ci    OPENSSL_free(wNAF_len);
792e1051a39Sopenharmony_ci    if (wNAF != NULL) {
793e1051a39Sopenharmony_ci        signed char **w;
794e1051a39Sopenharmony_ci
795e1051a39Sopenharmony_ci        for (w = wNAF; *w != NULL; w++)
796e1051a39Sopenharmony_ci            OPENSSL_free(*w);
797e1051a39Sopenharmony_ci
798e1051a39Sopenharmony_ci        OPENSSL_free(wNAF);
799e1051a39Sopenharmony_ci    }
800e1051a39Sopenharmony_ci    if (val != NULL) {
801e1051a39Sopenharmony_ci        for (v = val; *v != NULL; v++)
802e1051a39Sopenharmony_ci            EC_POINT_clear_free(*v);
803e1051a39Sopenharmony_ci
804e1051a39Sopenharmony_ci        OPENSSL_free(val);
805e1051a39Sopenharmony_ci    }
806e1051a39Sopenharmony_ci    OPENSSL_free(val_sub);
807e1051a39Sopenharmony_ci    return ret;
808e1051a39Sopenharmony_ci}
809e1051a39Sopenharmony_ci
810e1051a39Sopenharmony_ci/*-
811e1051a39Sopenharmony_ci * ossl_ec_wNAF_precompute_mult()
812e1051a39Sopenharmony_ci * creates an EC_PRE_COMP object with preprecomputed multiples of the generator
813e1051a39Sopenharmony_ci * for use with wNAF splitting as implemented in ossl_ec_wNAF_mul().
814e1051a39Sopenharmony_ci *
815e1051a39Sopenharmony_ci * 'pre_comp->points' is an array of multiples of the generator
816e1051a39Sopenharmony_ci * of the following form:
817e1051a39Sopenharmony_ci * points[0] =     generator;
818e1051a39Sopenharmony_ci * points[1] = 3 * generator;
819e1051a39Sopenharmony_ci * ...
820e1051a39Sopenharmony_ci * points[2^(w-1)-1] =     (2^(w-1)-1) * generator;
821e1051a39Sopenharmony_ci * points[2^(w-1)]   =     2^blocksize * generator;
822e1051a39Sopenharmony_ci * points[2^(w-1)+1] = 3 * 2^blocksize * generator;
823e1051a39Sopenharmony_ci * ...
824e1051a39Sopenharmony_ci * points[2^(w-1)*(numblocks-1)-1] = (2^(w-1)) *  2^(blocksize*(numblocks-2)) * generator
825e1051a39Sopenharmony_ci * points[2^(w-1)*(numblocks-1)]   =              2^(blocksize*(numblocks-1)) * generator
826e1051a39Sopenharmony_ci * ...
827e1051a39Sopenharmony_ci * points[2^(w-1)*numblocks-1]     = (2^(w-1)) *  2^(blocksize*(numblocks-1)) * generator
828e1051a39Sopenharmony_ci * points[2^(w-1)*numblocks]       = NULL
829e1051a39Sopenharmony_ci */
830e1051a39Sopenharmony_ciint ossl_ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
831e1051a39Sopenharmony_ci{
832e1051a39Sopenharmony_ci    const EC_POINT *generator;
833e1051a39Sopenharmony_ci    EC_POINT *tmp_point = NULL, *base = NULL, **var;
834e1051a39Sopenharmony_ci    const BIGNUM *order;
835e1051a39Sopenharmony_ci    size_t i, bits, w, pre_points_per_block, blocksize, numblocks, num;
836e1051a39Sopenharmony_ci    EC_POINT **points = NULL;
837e1051a39Sopenharmony_ci    EC_PRE_COMP *pre_comp;
838e1051a39Sopenharmony_ci    int ret = 0;
839e1051a39Sopenharmony_ci    int used_ctx = 0;
840e1051a39Sopenharmony_ci#ifndef FIPS_MODULE
841e1051a39Sopenharmony_ci    BN_CTX *new_ctx = NULL;
842e1051a39Sopenharmony_ci#endif
843e1051a39Sopenharmony_ci
844e1051a39Sopenharmony_ci    /* if there is an old EC_PRE_COMP object, throw it away */
845e1051a39Sopenharmony_ci    EC_pre_comp_free(group);
846e1051a39Sopenharmony_ci    if ((pre_comp = ec_pre_comp_new(group)) == NULL)
847e1051a39Sopenharmony_ci        return 0;
848e1051a39Sopenharmony_ci
849e1051a39Sopenharmony_ci    generator = EC_GROUP_get0_generator(group);
850e1051a39Sopenharmony_ci    if (generator == NULL) {
851e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_UNDEFINED_GENERATOR);
852e1051a39Sopenharmony_ci        goto err;
853e1051a39Sopenharmony_ci    }
854e1051a39Sopenharmony_ci
855e1051a39Sopenharmony_ci#ifndef FIPS_MODULE
856e1051a39Sopenharmony_ci    if (ctx == NULL)
857e1051a39Sopenharmony_ci        ctx = new_ctx = BN_CTX_new();
858e1051a39Sopenharmony_ci#endif
859e1051a39Sopenharmony_ci    if (ctx == NULL)
860e1051a39Sopenharmony_ci        goto err;
861e1051a39Sopenharmony_ci
862e1051a39Sopenharmony_ci    BN_CTX_start(ctx);
863e1051a39Sopenharmony_ci    used_ctx = 1;
864e1051a39Sopenharmony_ci
865e1051a39Sopenharmony_ci    order = EC_GROUP_get0_order(group);
866e1051a39Sopenharmony_ci    if (order == NULL)
867e1051a39Sopenharmony_ci        goto err;
868e1051a39Sopenharmony_ci    if (BN_is_zero(order)) {
869e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_ORDER);
870e1051a39Sopenharmony_ci        goto err;
871e1051a39Sopenharmony_ci    }
872e1051a39Sopenharmony_ci
873e1051a39Sopenharmony_ci    bits = BN_num_bits(order);
874e1051a39Sopenharmony_ci    /*
875e1051a39Sopenharmony_ci     * The following parameters mean we precompute (approximately) one point
876e1051a39Sopenharmony_ci     * per bit. TBD: The combination 8, 4 is perfect for 160 bits; for other
877e1051a39Sopenharmony_ci     * bit lengths, other parameter combinations might provide better
878e1051a39Sopenharmony_ci     * efficiency.
879e1051a39Sopenharmony_ci     */
880e1051a39Sopenharmony_ci    blocksize = 8;
881e1051a39Sopenharmony_ci    w = 4;
882e1051a39Sopenharmony_ci    if (EC_window_bits_for_scalar_size(bits) > w) {
883e1051a39Sopenharmony_ci        /* let's not make the window too small ... */
884e1051a39Sopenharmony_ci        w = EC_window_bits_for_scalar_size(bits);
885e1051a39Sopenharmony_ci    }
886e1051a39Sopenharmony_ci
887e1051a39Sopenharmony_ci    numblocks = (bits + blocksize - 1) / blocksize; /* max. number of blocks
888e1051a39Sopenharmony_ci                                                     * to use for wNAF
889e1051a39Sopenharmony_ci                                                     * splitting */
890e1051a39Sopenharmony_ci
891e1051a39Sopenharmony_ci    pre_points_per_block = (size_t)1 << (w - 1);
892e1051a39Sopenharmony_ci    num = pre_points_per_block * numblocks; /* number of points to compute
893e1051a39Sopenharmony_ci                                             * and store */
894e1051a39Sopenharmony_ci
895e1051a39Sopenharmony_ci    points = OPENSSL_malloc(sizeof(*points) * (num + 1));
896e1051a39Sopenharmony_ci    if (points == NULL) {
897e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
898e1051a39Sopenharmony_ci        goto err;
899e1051a39Sopenharmony_ci    }
900e1051a39Sopenharmony_ci
901e1051a39Sopenharmony_ci    var = points;
902e1051a39Sopenharmony_ci    var[num] = NULL;            /* pivot */
903e1051a39Sopenharmony_ci    for (i = 0; i < num; i++) {
904e1051a39Sopenharmony_ci        if ((var[i] = EC_POINT_new(group)) == NULL) {
905e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
906e1051a39Sopenharmony_ci            goto err;
907e1051a39Sopenharmony_ci        }
908e1051a39Sopenharmony_ci    }
909e1051a39Sopenharmony_ci
910e1051a39Sopenharmony_ci    if ((tmp_point = EC_POINT_new(group)) == NULL
911e1051a39Sopenharmony_ci        || (base = EC_POINT_new(group)) == NULL) {
912e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
913e1051a39Sopenharmony_ci        goto err;
914e1051a39Sopenharmony_ci    }
915e1051a39Sopenharmony_ci
916e1051a39Sopenharmony_ci    if (!EC_POINT_copy(base, generator))
917e1051a39Sopenharmony_ci        goto err;
918e1051a39Sopenharmony_ci
919e1051a39Sopenharmony_ci    /* do the precomputation */
920e1051a39Sopenharmony_ci    for (i = 0; i < numblocks; i++) {
921e1051a39Sopenharmony_ci        size_t j;
922e1051a39Sopenharmony_ci
923e1051a39Sopenharmony_ci        if (!EC_POINT_dbl(group, tmp_point, base, ctx))
924e1051a39Sopenharmony_ci            goto err;
925e1051a39Sopenharmony_ci
926e1051a39Sopenharmony_ci        if (!EC_POINT_copy(*var++, base))
927e1051a39Sopenharmony_ci            goto err;
928e1051a39Sopenharmony_ci
929e1051a39Sopenharmony_ci        for (j = 1; j < pre_points_per_block; j++, var++) {
930e1051a39Sopenharmony_ci            /*
931e1051a39Sopenharmony_ci             * calculate odd multiples of the current base point
932e1051a39Sopenharmony_ci             */
933e1051a39Sopenharmony_ci            if (!EC_POINT_add(group, *var, tmp_point, *(var - 1), ctx))
934e1051a39Sopenharmony_ci                goto err;
935e1051a39Sopenharmony_ci        }
936e1051a39Sopenharmony_ci
937e1051a39Sopenharmony_ci        if (i < numblocks - 1) {
938e1051a39Sopenharmony_ci            /*
939e1051a39Sopenharmony_ci             * get the next base (multiply current one by 2^blocksize)
940e1051a39Sopenharmony_ci             */
941e1051a39Sopenharmony_ci            size_t k;
942e1051a39Sopenharmony_ci
943e1051a39Sopenharmony_ci            if (blocksize <= 2) {
944e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
945e1051a39Sopenharmony_ci                goto err;
946e1051a39Sopenharmony_ci            }
947e1051a39Sopenharmony_ci
948e1051a39Sopenharmony_ci            if (!EC_POINT_dbl(group, base, tmp_point, ctx))
949e1051a39Sopenharmony_ci                goto err;
950e1051a39Sopenharmony_ci            for (k = 2; k < blocksize; k++) {
951e1051a39Sopenharmony_ci                if (!EC_POINT_dbl(group, base, base, ctx))
952e1051a39Sopenharmony_ci                    goto err;
953e1051a39Sopenharmony_ci            }
954e1051a39Sopenharmony_ci        }
955e1051a39Sopenharmony_ci    }
956e1051a39Sopenharmony_ci
957e1051a39Sopenharmony_ci    if (group->meth->points_make_affine == NULL
958e1051a39Sopenharmony_ci        || !group->meth->points_make_affine(group, num, points, ctx))
959e1051a39Sopenharmony_ci        goto err;
960e1051a39Sopenharmony_ci
961e1051a39Sopenharmony_ci    pre_comp->group = group;
962e1051a39Sopenharmony_ci    pre_comp->blocksize = blocksize;
963e1051a39Sopenharmony_ci    pre_comp->numblocks = numblocks;
964e1051a39Sopenharmony_ci    pre_comp->w = w;
965e1051a39Sopenharmony_ci    pre_comp->points = points;
966e1051a39Sopenharmony_ci    points = NULL;
967e1051a39Sopenharmony_ci    pre_comp->num = num;
968e1051a39Sopenharmony_ci    SETPRECOMP(group, ec, pre_comp);
969e1051a39Sopenharmony_ci    pre_comp = NULL;
970e1051a39Sopenharmony_ci    ret = 1;
971e1051a39Sopenharmony_ci
972e1051a39Sopenharmony_ci err:
973e1051a39Sopenharmony_ci    if (used_ctx)
974e1051a39Sopenharmony_ci        BN_CTX_end(ctx);
975e1051a39Sopenharmony_ci#ifndef FIPS_MODULE
976e1051a39Sopenharmony_ci    BN_CTX_free(new_ctx);
977e1051a39Sopenharmony_ci#endif
978e1051a39Sopenharmony_ci    EC_ec_pre_comp_free(pre_comp);
979e1051a39Sopenharmony_ci    if (points) {
980e1051a39Sopenharmony_ci        EC_POINT **p;
981e1051a39Sopenharmony_ci
982e1051a39Sopenharmony_ci        for (p = points; *p != NULL; p++)
983e1051a39Sopenharmony_ci            EC_POINT_free(*p);
984e1051a39Sopenharmony_ci        OPENSSL_free(points);
985e1051a39Sopenharmony_ci    }
986e1051a39Sopenharmony_ci    EC_POINT_free(tmp_point);
987e1051a39Sopenharmony_ci    EC_POINT_free(base);
988e1051a39Sopenharmony_ci    return ret;
989e1051a39Sopenharmony_ci}
990e1051a39Sopenharmony_ci
991e1051a39Sopenharmony_ciint ossl_ec_wNAF_have_precompute_mult(const EC_GROUP *group)
992e1051a39Sopenharmony_ci{
993e1051a39Sopenharmony_ci    return HAVEPRECOMP(group, ec);
994e1051a39Sopenharmony_ci}
995