1160814Ssimon/* crypto/ec/ec2_mult.c */
2160814Ssimon/* ====================================================================
3160814Ssimon * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
4160814Ssimon *
5160814Ssimon * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
6160814Ssimon * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
7160814Ssimon * to the OpenSSL project.
8160814Ssimon *
9160814Ssimon * The ECC Code is licensed pursuant to the OpenSSL open source
10160814Ssimon * license provided below.
11160814Ssimon *
12160814Ssimon * The software is originally written by Sheueling Chang Shantz and
13160814Ssimon * Douglas Stebila of Sun Microsystems Laboratories.
14160814Ssimon *
15160814Ssimon */
16160814Ssimon/* ====================================================================
17160814Ssimon * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
18160814Ssimon *
19160814Ssimon * Redistribution and use in source and binary forms, with or without
20160814Ssimon * modification, are permitted provided that the following conditions
21160814Ssimon * are met:
22160814Ssimon *
23160814Ssimon * 1. Redistributions of source code must retain the above copyright
24296465Sdelphij *    notice, this list of conditions and the following disclaimer.
25160814Ssimon *
26160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright
27160814Ssimon *    notice, this list of conditions and the following disclaimer in
28160814Ssimon *    the documentation and/or other materials provided with the
29160814Ssimon *    distribution.
30160814Ssimon *
31160814Ssimon * 3. All advertising materials mentioning features or use of this
32160814Ssimon *    software must display the following acknowledgment:
33160814Ssimon *    "This product includes software developed by the OpenSSL Project
34160814Ssimon *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
35160814Ssimon *
36160814Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
37160814Ssimon *    endorse or promote products derived from this software without
38160814Ssimon *    prior written permission. For written permission, please contact
39160814Ssimon *    openssl-core@openssl.org.
40160814Ssimon *
41160814Ssimon * 5. Products derived from this software may not be called "OpenSSL"
42160814Ssimon *    nor may "OpenSSL" appear in their names without prior written
43160814Ssimon *    permission of the OpenSSL Project.
44160814Ssimon *
45160814Ssimon * 6. Redistributions of any form whatsoever must retain the following
46160814Ssimon *    acknowledgment:
47160814Ssimon *    "This product includes software developed by the OpenSSL Project
48160814Ssimon *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
49160814Ssimon *
50160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
51160814Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53160814Ssimon * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
54160814Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55160814Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56160814Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57160814Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59160814Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60160814Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
61160814Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE.
62160814Ssimon * ====================================================================
63160814Ssimon *
64160814Ssimon * This product includes cryptographic software written by Eric Young
65160814Ssimon * (eay@cryptsoft.com).  This product includes software written by Tim
66160814Ssimon * Hudson (tjh@cryptsoft.com).
67160814Ssimon *
68160814Ssimon */
69160814Ssimon
70160814Ssimon#include <openssl/err.h>
71160814Ssimon
72160814Ssimon#include "ec_lcl.h"
73160814Ssimon
74296465Sdelphij/*-
75296465Sdelphij * Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery projective
76160814Ssimon * coordinates.
77296465Sdelphij * Uses algorithm Mdouble in appendix of
78296465Sdelphij *     Lopez, J. and Dahab, R.  "Fast multiplication on elliptic curves over
79160814Ssimon *     GF(2^m) without precomputation".
80160814Ssimon * modified to not require precomputation of c=b^{2^{m-1}}.
81160814Ssimon */
82296465Sdelphijstatic int gf2m_Mdouble(const EC_GROUP *group, BIGNUM *x, BIGNUM *z,
83296465Sdelphij                        BN_CTX *ctx)
84296465Sdelphij{
85296465Sdelphij    BIGNUM *t1;
86296465Sdelphij    int ret = 0;
87160814Ssimon
88296465Sdelphij    /* Since Mdouble is static we can guarantee that ctx != NULL. */
89296465Sdelphij    BN_CTX_start(ctx);
90296465Sdelphij    t1 = BN_CTX_get(ctx);
91296465Sdelphij    if (t1 == NULL)
92296465Sdelphij        goto err;
93160814Ssimon
94296465Sdelphij    if (!group->meth->field_sqr(group, x, x, ctx))
95296465Sdelphij        goto err;
96296465Sdelphij    if (!group->meth->field_sqr(group, t1, z, ctx))
97296465Sdelphij        goto err;
98296465Sdelphij    if (!group->meth->field_mul(group, z, x, t1, ctx))
99296465Sdelphij        goto err;
100296465Sdelphij    if (!group->meth->field_sqr(group, x, x, ctx))
101296465Sdelphij        goto err;
102296465Sdelphij    if (!group->meth->field_sqr(group, t1, t1, ctx))
103296465Sdelphij        goto err;
104296465Sdelphij    if (!group->meth->field_mul(group, t1, &group->b, t1, ctx))
105296465Sdelphij        goto err;
106296465Sdelphij    if (!BN_GF2m_add(x, x, t1))
107296465Sdelphij        goto err;
108160814Ssimon
109296465Sdelphij    ret = 1;
110296465Sdelphij
111160814Ssimon err:
112296465Sdelphij    BN_CTX_end(ctx);
113296465Sdelphij    return ret;
114296465Sdelphij}
115160814Ssimon
116296465Sdelphij/*-
117296465Sdelphij * Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in Montgomery
118160814Ssimon * projective coordinates.
119296465Sdelphij * Uses algorithm Madd in appendix of
120296465Sdelphij *     Lopex, J. and Dahab, R.  "Fast multiplication on elliptic curves over
121160814Ssimon *     GF(2^m) without precomputation".
122160814Ssimon */
123296465Sdelphijstatic int gf2m_Madd(const EC_GROUP *group, const BIGNUM *x, BIGNUM *x1,
124296465Sdelphij                     BIGNUM *z1, const BIGNUM *x2, const BIGNUM *z2,
125296465Sdelphij                     BN_CTX *ctx)
126296465Sdelphij{
127296465Sdelphij    BIGNUM *t1, *t2;
128296465Sdelphij    int ret = 0;
129160814Ssimon
130296465Sdelphij    /* Since Madd is static we can guarantee that ctx != NULL. */
131296465Sdelphij    BN_CTX_start(ctx);
132296465Sdelphij    t1 = BN_CTX_get(ctx);
133296465Sdelphij    t2 = BN_CTX_get(ctx);
134296465Sdelphij    if (t2 == NULL)
135296465Sdelphij        goto err;
136160814Ssimon
137296465Sdelphij    if (!BN_copy(t1, x))
138296465Sdelphij        goto err;
139296465Sdelphij    if (!group->meth->field_mul(group, x1, x1, z2, ctx))
140296465Sdelphij        goto err;
141296465Sdelphij    if (!group->meth->field_mul(group, z1, z1, x2, ctx))
142296465Sdelphij        goto err;
143296465Sdelphij    if (!group->meth->field_mul(group, t2, x1, z1, ctx))
144296465Sdelphij        goto err;
145296465Sdelphij    if (!BN_GF2m_add(z1, z1, x1))
146296465Sdelphij        goto err;
147296465Sdelphij    if (!group->meth->field_sqr(group, z1, z1, ctx))
148296465Sdelphij        goto err;
149296465Sdelphij    if (!group->meth->field_mul(group, x1, z1, t1, ctx))
150296465Sdelphij        goto err;
151296465Sdelphij    if (!BN_GF2m_add(x1, x1, t2))
152296465Sdelphij        goto err;
153160814Ssimon
154296465Sdelphij    ret = 1;
155296465Sdelphij
156160814Ssimon err:
157296465Sdelphij    BN_CTX_end(ctx);
158296465Sdelphij    return ret;
159296465Sdelphij}
160160814Ssimon
161296465Sdelphij/*-
162296465Sdelphij * Compute the x, y affine coordinates from the point (x1, z1) (x2, z2)
163296465Sdelphij * using Montgomery point multiplication algorithm Mxy() in appendix of
164296465Sdelphij *     Lopex, J. and Dahab, R.  "Fast multiplication on elliptic curves over
165160814Ssimon *     GF(2^m) without precomputation".
166160814Ssimon * Returns:
167160814Ssimon *     0 on error
168160814Ssimon *     1 if return value should be the point at infinity
169160814Ssimon *     2 otherwise
170160814Ssimon */
171296465Sdelphijstatic int gf2m_Mxy(const EC_GROUP *group, const BIGNUM *x, const BIGNUM *y,
172296465Sdelphij                    BIGNUM *x1, BIGNUM *z1, BIGNUM *x2, BIGNUM *z2,
173296465Sdelphij                    BN_CTX *ctx)
174296465Sdelphij{
175296465Sdelphij    BIGNUM *t3, *t4, *t5;
176296465Sdelphij    int ret = 0;
177160814Ssimon
178296465Sdelphij    if (BN_is_zero(z1)) {
179296465Sdelphij        BN_zero(x2);
180296465Sdelphij        BN_zero(z2);
181296465Sdelphij        return 1;
182296465Sdelphij    }
183160814Ssimon
184296465Sdelphij    if (BN_is_zero(z2)) {
185296465Sdelphij        if (!BN_copy(x2, x))
186296465Sdelphij            return 0;
187296465Sdelphij        if (!BN_GF2m_add(z2, x, y))
188296465Sdelphij            return 0;
189296465Sdelphij        return 2;
190296465Sdelphij    }
191160814Ssimon
192296465Sdelphij    /* Since Mxy is static we can guarantee that ctx != NULL. */
193296465Sdelphij    BN_CTX_start(ctx);
194296465Sdelphij    t3 = BN_CTX_get(ctx);
195296465Sdelphij    t4 = BN_CTX_get(ctx);
196296465Sdelphij    t5 = BN_CTX_get(ctx);
197296465Sdelphij    if (t5 == NULL)
198296465Sdelphij        goto err;
199160814Ssimon
200296465Sdelphij    if (!BN_one(t5))
201296465Sdelphij        goto err;
202160814Ssimon
203296465Sdelphij    if (!group->meth->field_mul(group, t3, z1, z2, ctx))
204296465Sdelphij        goto err;
205160814Ssimon
206296465Sdelphij    if (!group->meth->field_mul(group, z1, z1, x, ctx))
207296465Sdelphij        goto err;
208296465Sdelphij    if (!BN_GF2m_add(z1, z1, x1))
209296465Sdelphij        goto err;
210296465Sdelphij    if (!group->meth->field_mul(group, z2, z2, x, ctx))
211296465Sdelphij        goto err;
212296465Sdelphij    if (!group->meth->field_mul(group, x1, z2, x1, ctx))
213296465Sdelphij        goto err;
214296465Sdelphij    if (!BN_GF2m_add(z2, z2, x2))
215296465Sdelphij        goto err;
216160814Ssimon
217296465Sdelphij    if (!group->meth->field_mul(group, z2, z2, z1, ctx))
218296465Sdelphij        goto err;
219296465Sdelphij    if (!group->meth->field_sqr(group, t4, x, ctx))
220296465Sdelphij        goto err;
221296465Sdelphij    if (!BN_GF2m_add(t4, t4, y))
222296465Sdelphij        goto err;
223296465Sdelphij    if (!group->meth->field_mul(group, t4, t4, t3, ctx))
224296465Sdelphij        goto err;
225296465Sdelphij    if (!BN_GF2m_add(t4, t4, z2))
226296465Sdelphij        goto err;
227160814Ssimon
228296465Sdelphij    if (!group->meth->field_mul(group, t3, t3, x, ctx))
229296465Sdelphij        goto err;
230296465Sdelphij    if (!group->meth->field_div(group, t3, t5, t3, ctx))
231296465Sdelphij        goto err;
232296465Sdelphij    if (!group->meth->field_mul(group, t4, t3, t4, ctx))
233296465Sdelphij        goto err;
234296465Sdelphij    if (!group->meth->field_mul(group, x2, x1, t3, ctx))
235296465Sdelphij        goto err;
236296465Sdelphij    if (!BN_GF2m_add(z2, x2, x))
237296465Sdelphij        goto err;
238296465Sdelphij
239296465Sdelphij    if (!group->meth->field_mul(group, z2, z2, t4, ctx))
240296465Sdelphij        goto err;
241296465Sdelphij    if (!BN_GF2m_add(z2, z2, y))
242296465Sdelphij        goto err;
243296465Sdelphij
244296465Sdelphij    ret = 2;
245296465Sdelphij
246160814Ssimon err:
247296465Sdelphij    BN_CTX_end(ctx);
248296465Sdelphij    return ret;
249296465Sdelphij}
250160814Ssimon
251296465Sdelphij/*-
252296465Sdelphij * Computes scalar*point and stores the result in r.
253160814Ssimon * point can not equal r.
254264285Sdelphij * Uses a modified algorithm 2P of
255296465Sdelphij *     Lopex, J. and Dahab, R.  "Fast multiplication on elliptic curves over
256160814Ssimon *     GF(2^m) without precomputation".
257264285Sdelphij *
258264285Sdelphij * To protect against side-channel attack the function uses constant time
259264285Sdelphij * swap avoiding conditional branches.
260160814Ssimon */
261296465Sdelphijstatic int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group,
262296465Sdelphij                                             EC_POINT *r,
263296465Sdelphij                                             const BIGNUM *scalar,
264296465Sdelphij                                             const EC_POINT *point,
265296465Sdelphij                                             BN_CTX *ctx)
266296465Sdelphij{
267296465Sdelphij    BIGNUM *x1, *x2, *z1, *z2;
268296465Sdelphij    int ret = 0, i, j;
269296465Sdelphij    BN_ULONG mask;
270160814Ssimon
271296465Sdelphij    if (r == point) {
272296465Sdelphij        ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, EC_R_INVALID_ARGUMENT);
273296465Sdelphij        return 0;
274296465Sdelphij    }
275160814Ssimon
276296465Sdelphij    /* if result should be point at infinity */
277296465Sdelphij    if ((scalar == NULL) || BN_is_zero(scalar) || (point == NULL) ||
278296465Sdelphij        EC_POINT_is_at_infinity(group, point)) {
279296465Sdelphij        return EC_POINT_set_to_infinity(group, r);
280296465Sdelphij    }
281160814Ssimon
282296465Sdelphij    /* only support affine coordinates */
283296465Sdelphij    if (!point->Z_is_one)
284296465Sdelphij        return 0;
285160814Ssimon
286296465Sdelphij    /*
287296465Sdelphij     * Since point_multiply is static we can guarantee that ctx != NULL.
288296465Sdelphij     */
289296465Sdelphij    BN_CTX_start(ctx);
290296465Sdelphij    x1 = BN_CTX_get(ctx);
291296465Sdelphij    z1 = BN_CTX_get(ctx);
292296465Sdelphij    if (z1 == NULL)
293296465Sdelphij        goto err;
294160814Ssimon
295296465Sdelphij    x2 = &r->X;
296296465Sdelphij    z2 = &r->Y;
297264285Sdelphij
298296465Sdelphij    bn_wexpand(x1, group->field.top);
299296465Sdelphij    bn_wexpand(z1, group->field.top);
300296465Sdelphij    bn_wexpand(x2, group->field.top);
301296465Sdelphij    bn_wexpand(z2, group->field.top);
302160814Ssimon
303296465Sdelphij    if (!BN_GF2m_mod_arr(x1, &point->X, group->poly))
304296465Sdelphij        goto err;               /* x1 = x */
305296465Sdelphij    if (!BN_one(z1))
306296465Sdelphij        goto err;               /* z1 = 1 */
307296465Sdelphij    if (!group->meth->field_sqr(group, z2, x1, ctx))
308296465Sdelphij        goto err;               /* z2 = x1^2 = x^2 */
309296465Sdelphij    if (!group->meth->field_sqr(group, x2, z2, ctx))
310296465Sdelphij        goto err;
311296465Sdelphij    if (!BN_GF2m_add(x2, x2, &group->b))
312296465Sdelphij        goto err;               /* x2 = x^4 + b */
313160814Ssimon
314296465Sdelphij    /* find top most bit and go one past it */
315296465Sdelphij    i = scalar->top - 1;
316296465Sdelphij    j = BN_BITS2 - 1;
317296465Sdelphij    mask = BN_TBIT;
318296465Sdelphij    while (!(scalar->d[i] & mask)) {
319296465Sdelphij        mask >>= 1;
320296465Sdelphij        j--;
321296465Sdelphij    }
322296465Sdelphij    mask >>= 1;
323296465Sdelphij    j--;
324296465Sdelphij    /* if top most bit was at word break, go to next word */
325296465Sdelphij    if (!mask) {
326296465Sdelphij        i--;
327296465Sdelphij        j = BN_BITS2 - 1;
328296465Sdelphij        mask = BN_TBIT;
329296465Sdelphij    }
330160814Ssimon
331296465Sdelphij    for (; i >= 0; i--) {
332296465Sdelphij        for (; j >= 0; j--) {
333296465Sdelphij            BN_consttime_swap(scalar->d[i] & mask, x1, x2, group->field.top);
334296465Sdelphij            BN_consttime_swap(scalar->d[i] & mask, z1, z2, group->field.top);
335296465Sdelphij            if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1, ctx))
336296465Sdelphij                goto err;
337296465Sdelphij            if (!gf2m_Mdouble(group, x1, z1, ctx))
338296465Sdelphij                goto err;
339296465Sdelphij            BN_consttime_swap(scalar->d[i] & mask, x1, x2, group->field.top);
340296465Sdelphij            BN_consttime_swap(scalar->d[i] & mask, z1, z2, group->field.top);
341296465Sdelphij            mask >>= 1;
342296465Sdelphij        }
343296465Sdelphij        j = BN_BITS2 - 1;
344296465Sdelphij        mask = BN_TBIT;
345296465Sdelphij    }
346160814Ssimon
347296465Sdelphij    /* convert out of "projective" coordinates */
348296465Sdelphij    i = gf2m_Mxy(group, &point->X, &point->Y, x1, z1, x2, z2, ctx);
349296465Sdelphij    if (i == 0)
350296465Sdelphij        goto err;
351296465Sdelphij    else if (i == 1) {
352296465Sdelphij        if (!EC_POINT_set_to_infinity(group, r))
353296465Sdelphij            goto err;
354296465Sdelphij    } else {
355296465Sdelphij        if (!BN_one(&r->Z))
356296465Sdelphij            goto err;
357296465Sdelphij        r->Z_is_one = 1;
358296465Sdelphij    }
359160814Ssimon
360296465Sdelphij    /* GF(2^m) field elements should always have BIGNUM::neg = 0 */
361296465Sdelphij    BN_set_negative(&r->X, 0);
362296465Sdelphij    BN_set_negative(&r->Y, 0);
363160814Ssimon
364296465Sdelphij    ret = 1;
365296465Sdelphij
366160814Ssimon err:
367296465Sdelphij    BN_CTX_end(ctx);
368296465Sdelphij    return ret;
369296465Sdelphij}
370160814Ssimon
371296465Sdelphij/*-
372296465Sdelphij * Computes the sum
373160814Ssimon *     scalar*group->generator + scalars[0]*points[0] + ... + scalars[num-1]*points[num-1]
374160814Ssimon * gracefully ignoring NULL scalar values.
375160814Ssimon */
376296465Sdelphijint ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r,
377296465Sdelphij                       const BIGNUM *scalar, size_t num,
378296465Sdelphij                       const EC_POINT *points[], const BIGNUM *scalars[],
379296465Sdelphij                       BN_CTX *ctx)
380296465Sdelphij{
381296465Sdelphij    BN_CTX *new_ctx = NULL;
382296465Sdelphij    int ret = 0;
383296465Sdelphij    size_t i;
384296465Sdelphij    EC_POINT *p = NULL;
385296465Sdelphij    EC_POINT *acc = NULL;
386160814Ssimon
387296465Sdelphij    if (ctx == NULL) {
388296465Sdelphij        ctx = new_ctx = BN_CTX_new();
389296465Sdelphij        if (ctx == NULL)
390296465Sdelphij            return 0;
391296465Sdelphij    }
392160814Ssimon
393296465Sdelphij    /*
394296465Sdelphij     * This implementation is more efficient than the wNAF implementation for
395296465Sdelphij     * 2 or fewer points.  Use the ec_wNAF_mul implementation for 3 or more
396296465Sdelphij     * points, or if we can perform a fast multiplication based on
397296465Sdelphij     * precomputation.
398296465Sdelphij     */
399296465Sdelphij    if ((scalar && (num > 1)) || (num > 2)
400296465Sdelphij        || (num == 0 && EC_GROUP_have_precompute_mult(group))) {
401296465Sdelphij        ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
402296465Sdelphij        goto err;
403296465Sdelphij    }
404160814Ssimon
405296465Sdelphij    if ((p = EC_POINT_new(group)) == NULL)
406296465Sdelphij        goto err;
407296465Sdelphij    if ((acc = EC_POINT_new(group)) == NULL)
408296465Sdelphij        goto err;
409160814Ssimon
410296465Sdelphij    if (!EC_POINT_set_to_infinity(group, acc))
411296465Sdelphij        goto err;
412160814Ssimon
413296465Sdelphij    if (scalar) {
414296465Sdelphij        if (!ec_GF2m_montgomery_point_multiply
415296465Sdelphij            (group, p, scalar, group->generator, ctx))
416296465Sdelphij            goto err;
417296465Sdelphij        if (BN_is_negative(scalar))
418296465Sdelphij            if (!group->meth->invert(group, p, ctx))
419296465Sdelphij                goto err;
420296465Sdelphij        if (!group->meth->add(group, acc, acc, p, ctx))
421296465Sdelphij            goto err;
422296465Sdelphij    }
423160814Ssimon
424296465Sdelphij    for (i = 0; i < num; i++) {
425296465Sdelphij        if (!ec_GF2m_montgomery_point_multiply
426296465Sdelphij            (group, p, scalars[i], points[i], ctx))
427296465Sdelphij            goto err;
428296465Sdelphij        if (BN_is_negative(scalars[i]))
429296465Sdelphij            if (!group->meth->invert(group, p, ctx))
430296465Sdelphij                goto err;
431296465Sdelphij        if (!group->meth->add(group, acc, acc, p, ctx))
432296465Sdelphij            goto err;
433296465Sdelphij    }
434160814Ssimon
435296465Sdelphij    if (!EC_POINT_copy(r, acc))
436296465Sdelphij        goto err;
437215697Ssimon
438296465Sdelphij    ret = 1;
439160814Ssimon
440296465Sdelphij err:
441296465Sdelphij    if (p)
442296465Sdelphij        EC_POINT_free(p);
443296465Sdelphij    if (acc)
444296465Sdelphij        EC_POINT_free(acc);
445296465Sdelphij    if (new_ctx != NULL)
446296465Sdelphij        BN_CTX_free(new_ctx);
447296465Sdelphij    return ret;
448296465Sdelphij}
449160814Ssimon
450296465Sdelphij/*
451296465Sdelphij * Precomputation for point multiplication: fall back to wNAF methods because
452296465Sdelphij * ec_GF2m_simple_mul() uses ec_wNAF_mul() if appropriate
453296465Sdelphij */
454160814Ssimon
455160814Ssimonint ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
456296465Sdelphij{
457296465Sdelphij    return ec_wNAF_precompute_mult(group, ctx);
458296465Sdelphij}
459160814Ssimon
460160814Ssimonint ec_GF2m_have_precompute_mult(const EC_GROUP *group)
461296465Sdelphij{
462296465Sdelphij    return ec_wNAF_have_precompute_mult(group);
463296465Sdelphij}
464