comment and error code update
[openssl.git] / crypto / ec / ec_mult.c
1 /* crypto/ec/ec_mult.c */
2 /* ====================================================================
3  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer. 
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in
14  *    the documentation and/or other materials provided with the
15  *    distribution.
16  *
17  * 3. All advertising materials mentioning features or use of this
18  *    software must display the following acknowledgment:
19  *    "This product includes software developed by the OpenSSL Project
20  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
21  *
22  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23  *    endorse or promote products derived from this software without
24  *    prior written permission. For written permission, please contact
25  *    openssl-core@openssl.org.
26  *
27  * 5. Products derived from this software may not be called "OpenSSL"
28  *    nor may "OpenSSL" appear in their names without prior written
29  *    permission of the OpenSSL Project.
30  *
31  * 6. Redistributions of any form whatsoever must retain the following
32  *    acknowledgment:
33  *    "This product includes software developed by the OpenSSL Project
34  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
35  *
36  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47  * OF THE POSSIBILITY OF SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This product includes cryptographic software written by Eric Young
51  * (eay@cryptsoft.com).  This product includes software written by Tim
52  * Hudson (tjh@cryptsoft.com).
53  *
54  */
55
56 #include <openssl/err.h>
57
58 #include "ec_lcl.h"
59
60
61 /* TODO: width-m NAFs */
62
63 /* TODO: optional Lim-Lee precomputation for the generator */
64
65
66 /* this is just BN_window_bits_for_exponent_size from bn_lcl.h for now;
67  * the table should be updated for EC */ /* TODO */
68 #define EC_window_bits_for_scalar_size(b) \
69                 ((b) > 671 ? 6 : \
70                  (b) > 239 ? 5 : \
71                  (b) >  79 ? 4 : \
72                  (b) >  23 ? 3 : 1)
73
74 /* Compute
75  *      \sum scalars[i]*points[i]
76  * where
77  *      scalar*generator
78  * is included in the addition if scalar != NULL
79  */
80 int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, BIGNUM *scalar,
81         size_t num, EC_POINT *points[], BIGNUM *scalars[], BN_CTX *ctx)
82         {
83         BN_CTX *new_ctx = NULL;
84         EC_POINT *generator = NULL;
85         EC_POINT *tmp = NULL;
86         size_t totalnum;
87         size_t i, j;
88         int k, t;
89         int r_is_at_infinity = 1;
90         size_t max_bits = 0;
91         size_t *wsize = NULL; /* individual window sizes */
92         unsigned long *wbits = NULL; /* individual window contents */
93         int *wpos = NULL; /* position of bottom bit of current individual windows
94                            * (wpos[i] is valid if wbits[i] != 0) */
95         size_t num_val;
96         EC_POINT **val = NULL; /* precomputation */
97         EC_POINT **v;
98         EC_POINT ***val_sub = NULL; /* pointers to sub-arrays of 'val' */
99         int ret = 0;
100         
101         if (scalar != NULL)
102                 {
103                 generator = EC_GROUP_get0_generator(group);
104                 if (generator == NULL)
105                         {
106                         ECerr(EC_F_EC_POINTS_MUL, EC_R_UNDEFINED_GENERATOR);
107                         return 0;
108                         }
109                 }
110         
111         for (i = 0; i < num; i++)
112                 {
113                 if (group->meth != points[i]->meth)
114                         {
115                         ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);
116                         return 0;
117                         }
118                 }
119
120         totalnum = num + (scalar != NULL);
121
122         wsize = OPENSSL_malloc(totalnum * sizeof wsize[0]);
123         wbits = OPENSSL_malloc(totalnum * sizeof wbits[0]);
124         wpos = OPENSSL_malloc(totalnum * sizeof wpos[0]);
125         if (wsize == NULL || wbits == NULL || wpos == NULL) goto err;
126
127         /* num_val := total number of points to precompute */
128         num_val = 0;
129         for (i = 0; i < totalnum; i++)
130                 {
131                 size_t bits;
132
133                 bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(scalar);
134                 wsize[i] = EC_window_bits_for_scalar_size(bits);
135                 num_val += 1 << (wsize[i] - 1);
136                 if (bits > max_bits)
137                         max_bits = bits;
138                 wbits[i] = 0;
139                 wpos[i] = 0;
140                 }
141
142         /* all precomputed points go into a single array 'val',
143          * 'val_sub[i]' is a pointer to the subarray for the i-th point */
144         val = OPENSSL_malloc((num_val + 1) * sizeof val[0]);
145         if (val == NULL) goto err;
146         val[num_val] = NULL; /* pivot element */
147
148         val_sub = OPENSSL_malloc(totalnum * sizeof val_sub[0]);
149         if (val_sub == NULL) goto err;
150
151         /* allocate points for precomputation */
152         v = val;
153         for (i = 0; i < totalnum; i++)
154                 {
155                 val_sub[i] = v;
156                 for (j = 0; j < (1 << (wsize[i] - 1)); j++)
157                         {
158                         *v = EC_POINT_new(group);
159                         if (*v == NULL) goto err;
160                         v++;
161                         }
162                 }
163         if (!(v == val + num_val))
164                 {
165                 ECerr(EC_F_EC_POINTS_MUL, ERR_R_INTERNAL_ERROR);
166                 goto err;
167                 }
168
169         if (ctx == NULL)
170                 {
171                 ctx = new_ctx = BN_CTX_new();
172                 if (ctx == NULL)
173                         goto err;
174                 }
175         
176         tmp = EC_POINT_new(group);
177         if (tmp == NULL) goto err;
178
179         /* prepare precomputed values:
180          *    val_sub[i][0] :=     points[i]
181          *    val_sub[i][1] := 3 * points[i]
182          *    val_sub[i][2] := 5 * points[i]
183          *    ...
184          */
185         for (i = 0; i < totalnum; i++)
186                 {
187                 if (i < num)
188                         {
189                         if (!EC_POINT_copy(val_sub[i][0], points[i])) goto err;
190                         }
191                 else
192                         {
193                         if (!EC_POINT_copy(val_sub[i][0], generator)) goto err;
194                         }
195
196                 if (wsize[i] > 1)
197                         {
198                         if (!EC_POINT_dbl(group, tmp, val_sub[i][0], ctx)) goto err;
199                         for (j = 1; j < (1 << (wsize[i] - 1)); j++)
200                                 {
201                                 if (!EC_POINT_add(group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx)) goto err;
202                                 }
203                         }
204                 }
205
206 #if 1 /* optional, maybe we should only do this if total_num > 1 */
207         if (!EC_POINTs_make_affine(group, num_val, val, ctx)) goto err;
208 #endif
209
210         r_is_at_infinity = 1;
211
212         for (k = max_bits - 1; k >= 0; k--)
213                 {
214                 if (!r_is_at_infinity)
215                         {
216                         if (!EC_POINT_dbl(group, r, r, ctx)) goto err;
217                         }
218                 
219                 for (i = 0; i < totalnum; i++)
220                         {
221                         if (wbits[i] == 0)
222                                 {
223                                 BIGNUM *s;
224
225                                 s = i < num ? scalars[i] : scalar;
226
227                                 if (BN_is_bit_set(s, k))
228                                         {
229                                         /* look at bits  k - wsize[i] + 1 .. k  for this window */
230                                         t = k - wsize[i] + 1;
231                                         while (!BN_is_bit_set(s, t)) /* BN_is_bit_set is false for t < 0 */
232                                                 t++;
233                                         wpos[i] = t;
234                                         wbits[i] = 1;
235                                         for (t = k - 1; t >= wpos[i]; t--)
236                                                 {
237                                                 wbits[i] <<= 1;
238                                                 if (BN_is_bit_set(s, t))
239                                                         wbits[i]++;
240                                                 }
241                                         /* now wbits[i] is the odd bit pattern at bits wpos[i] .. k */
242                                         }
243                                 }
244                         
245                         if ((wbits[i] != 0) && (wpos[i] == k))
246                                 {
247                                 if (r_is_at_infinity)
248                                         {
249                                         if (!EC_POINT_copy(r, val_sub[i][wbits[i] >> 1])) goto err;
250                                         r_is_at_infinity = 0;
251                                         }
252                                 else
253                                         {
254                                         if (!EC_POINT_add(group, r, r, val_sub[i][wbits[i] >> 1], ctx)) goto err;
255                                         }
256                                 wbits[i] = 0;
257                                 }
258                         }
259                 }
260
261         if (r_is_at_infinity)
262                 if (!EC_POINT_set_to_infinity(group, r)) goto err;
263         
264         ret = 1;
265
266  err:
267         if (new_ctx != NULL)
268                 BN_CTX_free(new_ctx);
269         if (tmp != NULL)
270                 EC_POINT_free(tmp);
271         if (wsize != NULL)
272                 OPENSSL_free(wsize);
273         if (wbits != NULL)
274                 OPENSSL_free(wbits);
275         if (wpos != NULL)
276                 OPENSSL_free(wpos);
277         if (val != NULL)
278                 {
279                 for (v = val; *v != NULL; v++)
280                         EC_POINT_clear_free(*v);
281
282                 OPENSSL_free(val);
283                 }
284         if (val_sub != NULL)
285                 {
286                 OPENSSL_free(val_sub);
287                 }
288         return ret;
289         }