]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - crypto/openssl/crypto/ec/ec2_mult.c
Fix multiple OpenSSL vulnerabilities.
[FreeBSD/releng/9.3.git] / crypto / openssl / crypto / ec / ec2_mult.c
1 /* crypto/ec/ec2_mult.c */
2 /* ====================================================================
3  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
4  *
5  * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
6  * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
7  * to the OpenSSL project.
8  *
9  * The ECC Code is licensed pursuant to the OpenSSL open source
10  * license provided below.
11  *
12  * The software is originally written by Sheueling Chang Shantz and
13  * Douglas Stebila of Sun Microsystems Laboratories.
14  *
15  */
16 /* ====================================================================
17  * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
18  *
19  * Redistribution and use in source and binary forms, with or without
20  * modification, are permitted provided that the following conditions
21  * are met:
22  *
23  * 1. Redistributions of source code must retain the above copyright
24  *    notice, this list of conditions and the following disclaimer.
25  *
26  * 2. Redistributions in binary form must reproduce the above copyright
27  *    notice, this list of conditions and the following disclaimer in
28  *    the documentation and/or other materials provided with the
29  *    distribution.
30  *
31  * 3. All advertising materials mentioning features or use of this
32  *    software must display the following acknowledgment:
33  *    "This product includes software developed by the OpenSSL Project
34  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
35  *
36  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
37  *    endorse or promote products derived from this software without
38  *    prior written permission. For written permission, please contact
39  *    openssl-core@openssl.org.
40  *
41  * 5. Products derived from this software may not be called "OpenSSL"
42  *    nor may "OpenSSL" appear in their names without prior written
43  *    permission of the OpenSSL Project.
44  *
45  * 6. Redistributions of any form whatsoever must retain the following
46  *    acknowledgment:
47  *    "This product includes software developed by the OpenSSL Project
48  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
49  *
50  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
51  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
54  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
61  * OF THE POSSIBILITY OF SUCH DAMAGE.
62  * ====================================================================
63  *
64  * This product includes cryptographic software written by Eric Young
65  * (eay@cryptsoft.com).  This product includes software written by Tim
66  * Hudson (tjh@cryptsoft.com).
67  *
68  */
69
70 #include <openssl/err.h>
71
72 #include "ec_lcl.h"
73
74 /*-
75  * Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery projective
76  * coordinates.
77  * Uses algorithm Mdouble in appendix of
78  *     Lopez, J. and Dahab, R.  "Fast multiplication on elliptic curves over
79  *     GF(2^m) without precomputation".
80  * modified to not require precomputation of c=b^{2^{m-1}}.
81  */
82 static int gf2m_Mdouble(const EC_GROUP *group, BIGNUM *x, BIGNUM *z,
83                         BN_CTX *ctx)
84 {
85     BIGNUM *t1;
86     int ret = 0;
87
88     /* Since Mdouble is static we can guarantee that ctx != NULL. */
89     BN_CTX_start(ctx);
90     t1 = BN_CTX_get(ctx);
91     if (t1 == NULL)
92         goto err;
93
94     if (!group->meth->field_sqr(group, x, x, ctx))
95         goto err;
96     if (!group->meth->field_sqr(group, t1, z, ctx))
97         goto err;
98     if (!group->meth->field_mul(group, z, x, t1, ctx))
99         goto err;
100     if (!group->meth->field_sqr(group, x, x, ctx))
101         goto err;
102     if (!group->meth->field_sqr(group, t1, t1, ctx))
103         goto err;
104     if (!group->meth->field_mul(group, t1, &group->b, t1, ctx))
105         goto err;
106     if (!BN_GF2m_add(x, x, t1))
107         goto err;
108
109     ret = 1;
110
111  err:
112     BN_CTX_end(ctx);
113     return ret;
114 }
115
116 /*-
117  * Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in Montgomery
118  * projective coordinates.
119  * Uses algorithm Madd in appendix of
120  *     Lopex, J. and Dahab, R.  "Fast multiplication on elliptic curves over
121  *     GF(2^m) without precomputation".
122  */
123 static int gf2m_Madd(const EC_GROUP *group, const BIGNUM *x, BIGNUM *x1,
124                      BIGNUM *z1, const BIGNUM *x2, const BIGNUM *z2,
125                      BN_CTX *ctx)
126 {
127     BIGNUM *t1, *t2;
128     int ret = 0;
129
130     /* Since Madd is static we can guarantee that ctx != NULL. */
131     BN_CTX_start(ctx);
132     t1 = BN_CTX_get(ctx);
133     t2 = BN_CTX_get(ctx);
134     if (t2 == NULL)
135         goto err;
136
137     if (!BN_copy(t1, x))
138         goto err;
139     if (!group->meth->field_mul(group, x1, x1, z2, ctx))
140         goto err;
141     if (!group->meth->field_mul(group, z1, z1, x2, ctx))
142         goto err;
143     if (!group->meth->field_mul(group, t2, x1, z1, ctx))
144         goto err;
145     if (!BN_GF2m_add(z1, z1, x1))
146         goto err;
147     if (!group->meth->field_sqr(group, z1, z1, ctx))
148         goto err;
149     if (!group->meth->field_mul(group, x1, z1, t1, ctx))
150         goto err;
151     if (!BN_GF2m_add(x1, x1, t2))
152         goto err;
153
154     ret = 1;
155
156  err:
157     BN_CTX_end(ctx);
158     return ret;
159 }
160
161 /*-
162  * Compute the x, y affine coordinates from the point (x1, z1) (x2, z2)
163  * using Montgomery point multiplication algorithm Mxy() in appendix of
164  *     Lopex, J. and Dahab, R.  "Fast multiplication on elliptic curves over
165  *     GF(2^m) without precomputation".
166  * Returns:
167  *     0 on error
168  *     1 if return value should be the point at infinity
169  *     2 otherwise
170  */
171 static int gf2m_Mxy(const EC_GROUP *group, const BIGNUM *x, const BIGNUM *y,
172                     BIGNUM *x1, BIGNUM *z1, BIGNUM *x2, BIGNUM *z2,
173                     BN_CTX *ctx)
174 {
175     BIGNUM *t3, *t4, *t5;
176     int ret = 0;
177
178     if (BN_is_zero(z1)) {
179         BN_zero(x2);
180         BN_zero(z2);
181         return 1;
182     }
183
184     if (BN_is_zero(z2)) {
185         if (!BN_copy(x2, x))
186             return 0;
187         if (!BN_GF2m_add(z2, x, y))
188             return 0;
189         return 2;
190     }
191
192     /* Since Mxy is static we can guarantee that ctx != NULL. */
193     BN_CTX_start(ctx);
194     t3 = BN_CTX_get(ctx);
195     t4 = BN_CTX_get(ctx);
196     t5 = BN_CTX_get(ctx);
197     if (t5 == NULL)
198         goto err;
199
200     if (!BN_one(t5))
201         goto err;
202
203     if (!group->meth->field_mul(group, t3, z1, z2, ctx))
204         goto err;
205
206     if (!group->meth->field_mul(group, z1, z1, x, ctx))
207         goto err;
208     if (!BN_GF2m_add(z1, z1, x1))
209         goto err;
210     if (!group->meth->field_mul(group, z2, z2, x, ctx))
211         goto err;
212     if (!group->meth->field_mul(group, x1, z2, x1, ctx))
213         goto err;
214     if (!BN_GF2m_add(z2, z2, x2))
215         goto err;
216
217     if (!group->meth->field_mul(group, z2, z2, z1, ctx))
218         goto err;
219     if (!group->meth->field_sqr(group, t4, x, ctx))
220         goto err;
221     if (!BN_GF2m_add(t4, t4, y))
222         goto err;
223     if (!group->meth->field_mul(group, t4, t4, t3, ctx))
224         goto err;
225     if (!BN_GF2m_add(t4, t4, z2))
226         goto err;
227
228     if (!group->meth->field_mul(group, t3, t3, x, ctx))
229         goto err;
230     if (!group->meth->field_div(group, t3, t5, t3, ctx))
231         goto err;
232     if (!group->meth->field_mul(group, t4, t3, t4, ctx))
233         goto err;
234     if (!group->meth->field_mul(group, x2, x1, t3, ctx))
235         goto err;
236     if (!BN_GF2m_add(z2, x2, x))
237         goto err;
238
239     if (!group->meth->field_mul(group, z2, z2, t4, ctx))
240         goto err;
241     if (!BN_GF2m_add(z2, z2, y))
242         goto err;
243
244     ret = 2;
245
246  err:
247     BN_CTX_end(ctx);
248     return ret;
249 }
250
251 /*-
252  * Computes scalar*point and stores the result in r.
253  * point can not equal r.
254  * Uses a modified algorithm 2P of
255  *     Lopex, J. and Dahab, R.  "Fast multiplication on elliptic curves over
256  *     GF(2^m) without precomputation".
257  *
258  * To protect against side-channel attack the function uses constant time
259  * swap avoiding conditional branches.
260  */
261 static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group,
262                                              EC_POINT *r,
263                                              const BIGNUM *scalar,
264                                              const EC_POINT *point,
265                                              BN_CTX *ctx)
266 {
267     BIGNUM *x1, *x2, *z1, *z2;
268     int ret = 0, i, j;
269     BN_ULONG mask;
270
271     if (r == point) {
272         ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, EC_R_INVALID_ARGUMENT);
273         return 0;
274     }
275
276     /* if result should be point at infinity */
277     if ((scalar == NULL) || BN_is_zero(scalar) || (point == NULL) ||
278         EC_POINT_is_at_infinity(group, point)) {
279         return EC_POINT_set_to_infinity(group, r);
280     }
281
282     /* only support affine coordinates */
283     if (!point->Z_is_one)
284         return 0;
285
286     /*
287      * Since point_multiply is static we can guarantee that ctx != NULL.
288      */
289     BN_CTX_start(ctx);
290     x1 = BN_CTX_get(ctx);
291     z1 = BN_CTX_get(ctx);
292     if (z1 == NULL)
293         goto err;
294
295     x2 = &r->X;
296     z2 = &r->Y;
297
298     bn_wexpand(x1, group->field.top);
299     bn_wexpand(z1, group->field.top);
300     bn_wexpand(x2, group->field.top);
301     bn_wexpand(z2, group->field.top);
302
303     if (!BN_GF2m_mod_arr(x1, &point->X, group->poly))
304         goto err;               /* x1 = x */
305     if (!BN_one(z1))
306         goto err;               /* z1 = 1 */
307     if (!group->meth->field_sqr(group, z2, x1, ctx))
308         goto err;               /* z2 = x1^2 = x^2 */
309     if (!group->meth->field_sqr(group, x2, z2, ctx))
310         goto err;
311     if (!BN_GF2m_add(x2, x2, &group->b))
312         goto err;               /* x2 = x^4 + b */
313
314     /* find top most bit and go one past it */
315     i = scalar->top - 1;
316     j = BN_BITS2 - 1;
317     mask = BN_TBIT;
318     while (!(scalar->d[i] & mask)) {
319         mask >>= 1;
320         j--;
321     }
322     mask >>= 1;
323     j--;
324     /* if top most bit was at word break, go to next word */
325     if (!mask) {
326         i--;
327         j = BN_BITS2 - 1;
328         mask = BN_TBIT;
329     }
330
331     for (; i >= 0; i--) {
332         for (; j >= 0; j--) {
333             BN_consttime_swap(scalar->d[i] & mask, x1, x2, group->field.top);
334             BN_consttime_swap(scalar->d[i] & mask, z1, z2, group->field.top);
335             if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1, ctx))
336                 goto err;
337             if (!gf2m_Mdouble(group, x1, z1, ctx))
338                 goto err;
339             BN_consttime_swap(scalar->d[i] & mask, x1, x2, group->field.top);
340             BN_consttime_swap(scalar->d[i] & mask, z1, z2, group->field.top);
341             mask >>= 1;
342         }
343         j = BN_BITS2 - 1;
344         mask = BN_TBIT;
345     }
346
347     /* convert out of "projective" coordinates */
348     i = gf2m_Mxy(group, &point->X, &point->Y, x1, z1, x2, z2, ctx);
349     if (i == 0)
350         goto err;
351     else if (i == 1) {
352         if (!EC_POINT_set_to_infinity(group, r))
353             goto err;
354     } else {
355         if (!BN_one(&r->Z))
356             goto err;
357         r->Z_is_one = 1;
358     }
359
360     /* GF(2^m) field elements should always have BIGNUM::neg = 0 */
361     BN_set_negative(&r->X, 0);
362     BN_set_negative(&r->Y, 0);
363
364     ret = 1;
365
366  err:
367     BN_CTX_end(ctx);
368     return ret;
369 }
370
371 /*-
372  * Computes the sum
373  *     scalar*group->generator + scalars[0]*points[0] + ... + scalars[num-1]*points[num-1]
374  * gracefully ignoring NULL scalar values.
375  */
376 int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r,
377                        const BIGNUM *scalar, size_t num,
378                        const EC_POINT *points[], const BIGNUM *scalars[],
379                        BN_CTX *ctx)
380 {
381     BN_CTX *new_ctx = NULL;
382     int ret = 0;
383     size_t i;
384     EC_POINT *p = NULL;
385     EC_POINT *acc = NULL;
386
387     if (ctx == NULL) {
388         ctx = new_ctx = BN_CTX_new();
389         if (ctx == NULL)
390             return 0;
391     }
392
393     /*
394      * This implementation is more efficient than the wNAF implementation for
395      * 2 or fewer points.  Use the ec_wNAF_mul implementation for 3 or more
396      * points, or if we can perform a fast multiplication based on
397      * precomputation.
398      */
399     if ((scalar && (num > 1)) || (num > 2)
400         || (num == 0 && EC_GROUP_have_precompute_mult(group))) {
401         ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
402         goto err;
403     }
404
405     if ((p = EC_POINT_new(group)) == NULL)
406         goto err;
407     if ((acc = EC_POINT_new(group)) == NULL)
408         goto err;
409
410     if (!EC_POINT_set_to_infinity(group, acc))
411         goto err;
412
413     if (scalar) {
414         if (!ec_GF2m_montgomery_point_multiply
415             (group, p, scalar, group->generator, ctx))
416             goto err;
417         if (BN_is_negative(scalar))
418             if (!group->meth->invert(group, p, ctx))
419                 goto err;
420         if (!group->meth->add(group, acc, acc, p, ctx))
421             goto err;
422     }
423
424     for (i = 0; i < num; i++) {
425         if (!ec_GF2m_montgomery_point_multiply
426             (group, p, scalars[i], points[i], ctx))
427             goto err;
428         if (BN_is_negative(scalars[i]))
429             if (!group->meth->invert(group, p, ctx))
430                 goto err;
431         if (!group->meth->add(group, acc, acc, p, ctx))
432             goto err;
433     }
434
435     if (!EC_POINT_copy(r, acc))
436         goto err;
437
438     ret = 1;
439
440  err:
441     if (p)
442         EC_POINT_free(p);
443     if (acc)
444         EC_POINT_free(acc);
445     if (new_ctx != NULL)
446         BN_CTX_free(new_ctx);
447     return ret;
448 }
449
450 /*
451  * Precomputation for point multiplication: fall back to wNAF methods because
452  * ec_GF2m_simple_mul() uses ec_wNAF_mul() if appropriate
453  */
454
455 int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
456 {
457     return ec_wNAF_precompute_mult(group, ctx);
458 }
459
460 int ec_GF2m_have_precompute_mult(const EC_GROUP *group)
461 {
462     return ec_wNAF_have_precompute_mult(group);
463 }