summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/ec/ec2_mult.c
diff options
context:
space:
mode:
authortedu <>2014-05-06 03:56:27 +0000
committertedu <>2014-05-06 03:56:27 +0000
commit2518b24aa4315d557b967bff48dfc9efed909569 (patch)
treece2ee4fdddbbe61dd0ccb045a1604a3d92a86a00 /src/lib/libcrypto/ec/ec2_mult.c
parent0539604f5771dae2c3ecffa8122b5651ff283719 (diff)
downloadopenbsd-2518b24aa4315d557b967bff48dfc9efed909569.tar.gz
openbsd-2518b24aa4315d557b967bff48dfc9efed909569.tar.bz2
openbsd-2518b24aa4315d557b967bff48dfc9efed909569.zip
knf approximation
Diffstat (limited to '')
-rw-r--r--src/lib/libcrypto/ec/ec2_mult.c374
1 files changed, 213 insertions, 161 deletions
diff --git a/src/lib/libcrypto/ec/ec2_mult.c b/src/lib/libcrypto/ec/ec2_mult.c
index 1c575dc47a..040d7bb278 100644
--- a/src/lib/libcrypto/ec/ec2_mult.c
+++ b/src/lib/libcrypto/ec/ec2_mult.c
@@ -21,7 +21,7 @@
21 * are met: 21 * are met:
22 * 22 *
23 * 1. Redistributions of source code must retain the above copyright 23 * 1. Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer. 24 * notice, this list of conditions and the following disclaimer.
25 * 25 *
26 * 2. Redistributions in binary form must reproduce the above copyright 26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in 27 * notice, this list of conditions and the following disclaimer in
@@ -74,178 +74,215 @@
74#ifndef OPENSSL_NO_EC2M 74#ifndef OPENSSL_NO_EC2M
75 75
76 76
77/* Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery projective 77/* Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery projective
78 * coordinates. 78 * coordinates.
79 * Uses algorithm Mdouble in appendix of 79 * Uses algorithm Mdouble in appendix of
80 * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over 80 * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over
81 * GF(2^m) without precomputation" (CHES '99, LNCS 1717). 81 * GF(2^m) without precomputation" (CHES '99, LNCS 1717).
82 * modified to not require precomputation of c=b^{2^{m-1}}. 82 * modified to not require precomputation of c=b^{2^{m-1}}.
83 */ 83 */
84static int gf2m_Mdouble(const EC_GROUP *group, BIGNUM *x, BIGNUM *z, BN_CTX *ctx) 84static int
85 { 85gf2m_Mdouble(const EC_GROUP *group, BIGNUM *x, BIGNUM *z, BN_CTX *ctx)
86{
86 BIGNUM *t1; 87 BIGNUM *t1;
87 int ret = 0; 88 int ret = 0;
88 89
89 /* Since Mdouble is static we can guarantee that ctx != NULL. */ 90 /* Since Mdouble is static we can guarantee that ctx != NULL. */
90 BN_CTX_start(ctx); 91 BN_CTX_start(ctx);
91 t1 = BN_CTX_get(ctx); 92 t1 = BN_CTX_get(ctx);
92 if (t1 == NULL) goto err; 93 if (t1 == NULL)
94 goto err;
93 95
94 if (!group->meth->field_sqr(group, x, x, ctx)) goto err; 96 if (!group->meth->field_sqr(group, x, x, ctx))
95 if (!group->meth->field_sqr(group, t1, z, ctx)) goto err; 97 goto err;
96 if (!group->meth->field_mul(group, z, x, t1, ctx)) goto err; 98 if (!group->meth->field_sqr(group, t1, z, ctx))
97 if (!group->meth->field_sqr(group, x, x, ctx)) goto err; 99 goto err;
98 if (!group->meth->field_sqr(group, t1, t1, ctx)) goto err; 100 if (!group->meth->field_mul(group, z, x, t1, ctx))
99 if (!group->meth->field_mul(group, t1, &group->b, t1, ctx)) goto err; 101 goto err;
100 if (!BN_GF2m_add(x, x, t1)) goto err; 102 if (!group->meth->field_sqr(group, x, x, ctx))
103 goto err;
104 if (!group->meth->field_sqr(group, t1, t1, ctx))
105 goto err;
106 if (!group->meth->field_mul(group, t1, &group->b, t1, ctx))
107 goto err;
108 if (!BN_GF2m_add(x, x, t1))
109 goto err;
101 110
102 ret = 1; 111 ret = 1;
103 112
104 err: 113err:
105 BN_CTX_end(ctx); 114 BN_CTX_end(ctx);
106 return ret; 115 return ret;
107 } 116}
108 117
109/* Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in Montgomery 118/* Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in Montgomery
110 * projective coordinates. 119 * projective coordinates.
111 * Uses algorithm Madd in appendix of 120 * Uses algorithm Madd in appendix of
112 * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over 121 * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over
113 * GF(2^m) without precomputation" (CHES '99, LNCS 1717). 122 * GF(2^m) without precomputation" (CHES '99, LNCS 1717).
114 */ 123 */
115static int gf2m_Madd(const EC_GROUP *group, const BIGNUM *x, BIGNUM *x1, BIGNUM *z1, 124static int
116 const BIGNUM *x2, const BIGNUM *z2, BN_CTX *ctx) 125gf2m_Madd(const EC_GROUP *group, const BIGNUM *x, BIGNUM *x1, BIGNUM *z1,
117 { 126 const BIGNUM *x2, const BIGNUM *z2, BN_CTX *ctx)
127{
118 BIGNUM *t1, *t2; 128 BIGNUM *t1, *t2;
119 int ret = 0; 129 int ret = 0;
120 130
121 /* Since Madd is static we can guarantee that ctx != NULL. */ 131 /* Since Madd is static we can guarantee that ctx != NULL. */
122 BN_CTX_start(ctx); 132 BN_CTX_start(ctx);
123 t1 = BN_CTX_get(ctx); 133 t1 = BN_CTX_get(ctx);
124 t2 = BN_CTX_get(ctx); 134 t2 = BN_CTX_get(ctx);
125 if (t2 == NULL) goto err; 135 if (t2 == NULL)
136 goto err;
126 137
127 if (!BN_copy(t1, x)) goto err; 138 if (!BN_copy(t1, x))
128 if (!group->meth->field_mul(group, x1, x1, z2, ctx)) goto err; 139 goto err;
129 if (!group->meth->field_mul(group, z1, z1, x2, ctx)) goto err; 140 if (!group->meth->field_mul(group, x1, x1, z2, ctx))
130 if (!group->meth->field_mul(group, t2, x1, z1, ctx)) goto err; 141 goto err;
131 if (!BN_GF2m_add(z1, z1, x1)) goto err; 142 if (!group->meth->field_mul(group, z1, z1, x2, ctx))
132 if (!group->meth->field_sqr(group, z1, z1, ctx)) goto err; 143 goto err;
133 if (!group->meth->field_mul(group, x1, z1, t1, ctx)) goto err; 144 if (!group->meth->field_mul(group, t2, x1, z1, ctx))
134 if (!BN_GF2m_add(x1, x1, t2)) goto err; 145 goto err;
146 if (!BN_GF2m_add(z1, z1, x1))
147 goto err;
148 if (!group->meth->field_sqr(group, z1, z1, ctx))
149 goto err;
150 if (!group->meth->field_mul(group, x1, z1, t1, ctx))
151 goto err;
152 if (!BN_GF2m_add(x1, x1, t2))
153 goto err;
135 154
136 ret = 1; 155 ret = 1;
137 156
138 err: 157err:
139 BN_CTX_end(ctx); 158 BN_CTX_end(ctx);
140 return ret; 159 return ret;
141 } 160}
142 161
143/* Compute the x, y affine coordinates from the point (x1, z1) (x2, z2) 162/* Compute the x, y affine coordinates from the point (x1, z1) (x2, z2)
144 * using Montgomery point multiplication algorithm Mxy() in appendix of 163 * using Montgomery point multiplication algorithm Mxy() in appendix of
145 * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over 164 * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over
146 * GF(2^m) without precomputation" (CHES '99, LNCS 1717). 165 * GF(2^m) without precomputation" (CHES '99, LNCS 1717).
147 * Returns: 166 * Returns:
148 * 0 on error 167 * 0 on error
149 * 1 if return value should be the point at infinity 168 * 1 if return value should be the point at infinity
150 * 2 otherwise 169 * 2 otherwise
151 */ 170 */
152static int gf2m_Mxy(const EC_GROUP *group, const BIGNUM *x, const BIGNUM *y, BIGNUM *x1, 171static int
153 BIGNUM *z1, BIGNUM *x2, BIGNUM *z2, BN_CTX *ctx) 172gf2m_Mxy(const EC_GROUP *group, const BIGNUM *x, const BIGNUM *y, BIGNUM *x1,
154 { 173 BIGNUM *z1, BIGNUM *x2, BIGNUM *z2, BN_CTX *ctx)
174{
155 BIGNUM *t3, *t4, *t5; 175 BIGNUM *t3, *t4, *t5;
156 int ret = 0; 176 int ret = 0;
157 177
158 if (BN_is_zero(z1)) 178 if (BN_is_zero(z1)) {
159 {
160 BN_zero(x2); 179 BN_zero(x2);
161 BN_zero(z2); 180 BN_zero(z2);
162 return 1; 181 return 1;
163 } 182 }
164 183 if (BN_is_zero(z2)) {
165 if (BN_is_zero(z2)) 184 if (!BN_copy(x2, x))
166 { 185 return 0;
167 if (!BN_copy(x2, x)) return 0; 186 if (!BN_GF2m_add(z2, x, y))
168 if (!BN_GF2m_add(z2, x, y)) return 0; 187 return 0;
169 return 2; 188 return 2;
170 } 189 }
171
172 /* Since Mxy is static we can guarantee that ctx != NULL. */ 190 /* Since Mxy is static we can guarantee that ctx != NULL. */
173 BN_CTX_start(ctx); 191 BN_CTX_start(ctx);
174 t3 = BN_CTX_get(ctx); 192 t3 = BN_CTX_get(ctx);
175 t4 = BN_CTX_get(ctx); 193 t4 = BN_CTX_get(ctx);
176 t5 = BN_CTX_get(ctx); 194 t5 = BN_CTX_get(ctx);
177 if (t5 == NULL) goto err; 195 if (t5 == NULL)
196 goto err;
178 197
179 if (!BN_one(t5)) goto err; 198 if (!BN_one(t5))
199 goto err;
180 200
181 if (!group->meth->field_mul(group, t3, z1, z2, ctx)) goto err; 201 if (!group->meth->field_mul(group, t3, z1, z2, ctx))
202 goto err;
182 203
183 if (!group->meth->field_mul(group, z1, z1, x, ctx)) goto err; 204 if (!group->meth->field_mul(group, z1, z1, x, ctx))
184 if (!BN_GF2m_add(z1, z1, x1)) goto err; 205 goto err;
185 if (!group->meth->field_mul(group, z2, z2, x, ctx)) goto err; 206 if (!BN_GF2m_add(z1, z1, x1))
186 if (!group->meth->field_mul(group, x1, z2, x1, ctx)) goto err; 207 goto err;
187 if (!BN_GF2m_add(z2, z2, x2)) goto err; 208 if (!group->meth->field_mul(group, z2, z2, x, ctx))
209 goto err;
210 if (!group->meth->field_mul(group, x1, z2, x1, ctx))
211 goto err;
212 if (!BN_GF2m_add(z2, z2, x2))
213 goto err;
188 214
189 if (!group->meth->field_mul(group, z2, z2, z1, ctx)) goto err; 215 if (!group->meth->field_mul(group, z2, z2, z1, ctx))
190 if (!group->meth->field_sqr(group, t4, x, ctx)) goto err; 216 goto err;
191 if (!BN_GF2m_add(t4, t4, y)) goto err; 217 if (!group->meth->field_sqr(group, t4, x, ctx))
192 if (!group->meth->field_mul(group, t4, t4, t3, ctx)) goto err; 218 goto err;
193 if (!BN_GF2m_add(t4, t4, z2)) goto err; 219 if (!BN_GF2m_add(t4, t4, y))
220 goto err;
221 if (!group->meth->field_mul(group, t4, t4, t3, ctx))
222 goto err;
223 if (!BN_GF2m_add(t4, t4, z2))
224 goto err;
194 225
195 if (!group->meth->field_mul(group, t3, t3, x, ctx)) goto err; 226 if (!group->meth->field_mul(group, t3, t3, x, ctx))
196 if (!group->meth->field_div(group, t3, t5, t3, ctx)) goto err; 227 goto err;
197 if (!group->meth->field_mul(group, t4, t3, t4, ctx)) goto err; 228 if (!group->meth->field_div(group, t3, t5, t3, ctx))
198 if (!group->meth->field_mul(group, x2, x1, t3, ctx)) goto err; 229 goto err;
199 if (!BN_GF2m_add(z2, x2, x)) goto err; 230 if (!group->meth->field_mul(group, t4, t3, t4, ctx))
231 goto err;
232 if (!group->meth->field_mul(group, x2, x1, t3, ctx))
233 goto err;
234 if (!BN_GF2m_add(z2, x2, x))
235 goto err;
200 236
201 if (!group->meth->field_mul(group, z2, z2, t4, ctx)) goto err; 237 if (!group->meth->field_mul(group, z2, z2, t4, ctx))
202 if (!BN_GF2m_add(z2, z2, y)) goto err; 238 goto err;
239 if (!BN_GF2m_add(z2, z2, y))
240 goto err;
203 241
204 ret = 2; 242 ret = 2;
205 243
206 err: 244err:
207 BN_CTX_end(ctx); 245 BN_CTX_end(ctx);
208 return ret; 246 return ret;
209 } 247}
210 248
211 249
212/* Computes scalar*point and stores the result in r. 250/* Computes scalar*point and stores the result in r.
213 * point can not equal r. 251 * point can not equal r.
214 * Uses a modified algorithm 2P of 252 * Uses a modified algorithm 2P of
215 * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over 253 * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over
216 * GF(2^m) without precomputation" (CHES '99, LNCS 1717). 254 * GF(2^m) without precomputation" (CHES '99, LNCS 1717).
217 * 255 *
218 * To protect against side-channel attack the function uses constant time swap, 256 * To protect against side-channel attack the function uses constant time swap,
219 * avoiding conditional branches. 257 * avoiding conditional branches.
220 */ 258 */
221static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, 259static int
222 const EC_POINT *point, BN_CTX *ctx) 260ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, EC_POINT *r,
223 { 261 const BIGNUM *scalar, const EC_POINT *point, BN_CTX *ctx)
262{
224 BIGNUM *x1, *x2, *z1, *z2; 263 BIGNUM *x1, *x2, *z1, *z2;
225 int ret = 0, i; 264 int ret = 0, i;
226 BN_ULONG mask,word; 265 BN_ULONG mask, word;
227 266
228 if (r == point) 267 if (r == point) {
229 {
230 ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, EC_R_INVALID_ARGUMENT); 268 ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, EC_R_INVALID_ARGUMENT);
231 return 0; 269 return 0;
232 } 270 }
233
234 /* if result should be point at infinity */ 271 /* if result should be point at infinity */
235 if ((scalar == NULL) || BN_is_zero(scalar) || (point == NULL) || 272 if ((scalar == NULL) || BN_is_zero(scalar) || (point == NULL) ||
236 EC_POINT_is_at_infinity(group, point)) 273 EC_POINT_is_at_infinity(group, point)) {
237 {
238 return EC_POINT_set_to_infinity(group, r); 274 return EC_POINT_set_to_infinity(group, r);
239 } 275 }
240
241 /* only support affine coordinates */ 276 /* only support affine coordinates */
242 if (!point->Z_is_one) return 0; 277 if (!point->Z_is_one)
278 return 0;
243 279
244 /* Since point_multiply is static we can guarantee that ctx != NULL. */ 280 /* Since point_multiply is static we can guarantee that ctx != NULL. */
245 BN_CTX_start(ctx); 281 BN_CTX_start(ctx);
246 x1 = BN_CTX_get(ctx); 282 x1 = BN_CTX_get(ctx);
247 z1 = BN_CTX_get(ctx); 283 z1 = BN_CTX_get(ctx);
248 if (z1 == NULL) goto err; 284 if (z1 == NULL)
285 goto err;
249 286
250 x2 = &r->X; 287 x2 = &r->X;
251 z2 = &r->Y; 288 z2 = &r->Y;
@@ -255,53 +292,57 @@ static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, EC_POINT *r,
255 bn_wexpand(x2, group->field.top); 292 bn_wexpand(x2, group->field.top);
256 bn_wexpand(z2, group->field.top); 293 bn_wexpand(z2, group->field.top);
257 294
258 if (!BN_GF2m_mod_arr(x1, &point->X, group->poly)) goto err; /* x1 = x */ 295 if (!BN_GF2m_mod_arr(x1, &point->X, group->poly))
259 if (!BN_one(z1)) goto err; /* z1 = 1 */ 296 goto err; /* x1 = x */
260 if (!group->meth->field_sqr(group, z2, x1, ctx)) goto err; /* z2 = x1^2 = x^2 */ 297 if (!BN_one(z1))
261 if (!group->meth->field_sqr(group, x2, z2, ctx)) goto err; 298 goto err; /* z1 = 1 */
262 if (!BN_GF2m_add(x2, x2, &group->b)) goto err; /* x2 = x^4 + b */ 299 if (!group->meth->field_sqr(group, z2, x1, ctx))
300 goto err; /* z2 = x1^2 = x^2 */
301 if (!group->meth->field_sqr(group, x2, z2, ctx))
302 goto err;
303 if (!BN_GF2m_add(x2, x2, &group->b))
304 goto err; /* x2 = x^4 + b */
263 305
264 /* find top most bit and go one past it */ 306 /* find top most bit and go one past it */
265 i = scalar->top - 1; 307 i = scalar->top - 1;
266 mask = BN_TBIT; 308 mask = BN_TBIT;
267 word = scalar->d[i]; 309 word = scalar->d[i];
268 while (!(word & mask)) mask >>= 1; 310 while (!(word & mask))
311 mask >>= 1;
269 mask >>= 1; 312 mask >>= 1;
270 /* if top most bit was at word break, go to next word */ 313 /* if top most bit was at word break, go to next word */
271 if (!mask) 314 if (!mask) {
272 {
273 i--; 315 i--;
274 mask = BN_TBIT; 316 mask = BN_TBIT;
275 } 317 }
276 318 for (; i >= 0; i--) {
277 for (; i >= 0; i--)
278 {
279 word = scalar->d[i]; 319 word = scalar->d[i];
280 while (mask) 320 while (mask) {
281 {
282 BN_consttime_swap(word & mask, x1, x2, group->field.top); 321 BN_consttime_swap(word & mask, x1, x2, group->field.top);
283 BN_consttime_swap(word & mask, z1, z2, group->field.top); 322 BN_consttime_swap(word & mask, z1, z2, group->field.top);
284 if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1, ctx)) goto err; 323 if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1, ctx))
285 if (!gf2m_Mdouble(group, x1, z1, ctx)) goto err; 324 goto err;
325 if (!gf2m_Mdouble(group, x1, z1, ctx))
326 goto err;
286 BN_consttime_swap(word & mask, x1, x2, group->field.top); 327 BN_consttime_swap(word & mask, x1, x2, group->field.top);
287 BN_consttime_swap(word & mask, z1, z2, group->field.top); 328 BN_consttime_swap(word & mask, z1, z2, group->field.top);
288 mask >>= 1; 329 mask >>= 1;
289 }
290 mask = BN_TBIT;
291 } 330 }
331 mask = BN_TBIT;
332 }
292 333
293 /* convert out of "projective" coordinates */ 334 /* convert out of "projective" coordinates */
294 i = gf2m_Mxy(group, &point->X, &point->Y, x1, z1, x2, z2, ctx); 335 i = gf2m_Mxy(group, &point->X, &point->Y, x1, z1, x2, z2, ctx);
295 if (i == 0) goto err; 336 if (i == 0)
296 else if (i == 1) 337 goto err;
297 { 338 else if (i == 1) {
298 if (!EC_POINT_set_to_infinity(group, r)) goto err; 339 if (!EC_POINT_set_to_infinity(group, r))
299 } 340 goto err;
300 else 341 } else {
301 { 342 if (!BN_one(&r->Z))
302 if (!BN_one(&r->Z)) goto err; 343 goto err;
303 r->Z_is_one = 1; 344 r->Z_is_one = 1;
304 } 345 }
305 346
306 /* GF(2^m) field elements should always have BIGNUM::neg = 0 */ 347 /* GF(2^m) field elements should always have BIGNUM::neg = 0 */
307 BN_set_negative(&r->X, 0); 348 BN_set_negative(&r->X, 0);
@@ -309,87 +350,98 @@ static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, EC_POINT *r,
309 350
310 ret = 1; 351 ret = 1;
311 352
312 err: 353err:
313 BN_CTX_end(ctx); 354 BN_CTX_end(ctx);
314 return ret; 355 return ret;
315 } 356}
316 357
317 358
318/* Computes the sum 359/* Computes the sum
319 * scalar*group->generator + scalars[0]*points[0] + ... + scalars[num-1]*points[num-1] 360 * scalar*group->generator + scalars[0]*points[0] + ... + scalars[num-1]*points[num-1]
320 * gracefully ignoring NULL scalar values. 361 * gracefully ignoring NULL scalar values.
321 */ 362 */
322int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, 363int
323 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx) 364ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
324 { 365 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx)
366{
325 BN_CTX *new_ctx = NULL; 367 BN_CTX *new_ctx = NULL;
326 int ret = 0; 368 int ret = 0;
327 size_t i; 369 size_t i;
328 EC_POINT *p=NULL; 370 EC_POINT *p = NULL;
329 EC_POINT *acc = NULL; 371 EC_POINT *acc = NULL;
330 372
331 if (ctx == NULL) 373 if (ctx == NULL) {
332 {
333 ctx = new_ctx = BN_CTX_new(); 374 ctx = new_ctx = BN_CTX_new();
334 if (ctx == NULL) 375 if (ctx == NULL)
335 return 0; 376 return 0;
336 } 377 }
337 378 /*
338 /* This implementation is more efficient than the wNAF implementation for 2 379 * This implementation is more efficient than the wNAF implementation
339 * or fewer points. Use the ec_wNAF_mul implementation for 3 or more points, 380 * for 2 or fewer points. Use the ec_wNAF_mul implementation for 3
340 * or if we can perform a fast multiplication based on precomputation. 381 * or more points, or if we can perform a fast multiplication based
382 * on precomputation.
341 */ 383 */
342 if ((scalar && (num > 1)) || (num > 2) || (num == 0 && EC_GROUP_have_precompute_mult(group))) 384 if ((scalar && (num > 1)) || (num > 2) ||
343 { 385 (num == 0 && EC_GROUP_have_precompute_mult(group))) {
344 ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); 386 ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
345 goto err; 387 goto err;
346 } 388 }
347 389 if ((p = EC_POINT_new(group)) == NULL)
348 if ((p = EC_POINT_new(group)) == NULL) goto err; 390 goto err;
349 if ((acc = EC_POINT_new(group)) == NULL) goto err; 391 if ((acc = EC_POINT_new(group)) == NULL)
392 goto err;
350 393
351 if (!EC_POINT_set_to_infinity(group, acc)) goto err; 394 if (!EC_POINT_set_to_infinity(group, acc))
395 goto err;
352 396
353 if (scalar) 397 if (scalar) {
354 { 398 if (!ec_GF2m_montgomery_point_multiply(group, p, scalar, group->generator, ctx))
355 if (!ec_GF2m_montgomery_point_multiply(group, p, scalar, group->generator, ctx)) goto err; 399 goto err;
356 if (BN_is_negative(scalar)) 400 if (BN_is_negative(scalar))
357 if (!group->meth->invert(group, p, ctx)) goto err; 401 if (!group->meth->invert(group, p, ctx))
358 if (!group->meth->add(group, acc, acc, p, ctx)) goto err; 402 goto err;
359 } 403 if (!group->meth->add(group, acc, acc, p, ctx))
360 404 goto err;
361 for (i = 0; i < num; i++) 405 }
362 { 406 for (i = 0; i < num; i++) {
363 if (!ec_GF2m_montgomery_point_multiply(group, p, scalars[i], points[i], ctx)) goto err; 407 if (!ec_GF2m_montgomery_point_multiply(group, p, scalars[i], points[i], ctx))
408 goto err;
364 if (BN_is_negative(scalars[i])) 409 if (BN_is_negative(scalars[i]))
365 if (!group->meth->invert(group, p, ctx)) goto err; 410 if (!group->meth->invert(group, p, ctx))
366 if (!group->meth->add(group, acc, acc, p, ctx)) goto err; 411 goto err;
367 } 412 if (!group->meth->add(group, acc, acc, p, ctx))
413 goto err;
414 }
368 415
369 if (!EC_POINT_copy(r, acc)) goto err; 416 if (!EC_POINT_copy(r, acc))
417 goto err;
370 418
371 ret = 1; 419 ret = 1;
372 420
373 err: 421err:
374 if (p) EC_POINT_free(p); 422 if (p)
375 if (acc) EC_POINT_free(acc); 423 EC_POINT_free(p);
424 if (acc)
425 EC_POINT_free(acc);
376 if (new_ctx != NULL) 426 if (new_ctx != NULL)
377 BN_CTX_free(new_ctx); 427 BN_CTX_free(new_ctx);
378 return ret; 428 return ret;
379 } 429}
380 430
381 431
382/* Precomputation for point multiplication: fall back to wNAF methods 432/* Precomputation for point multiplication: fall back to wNAF methods
383 * because ec_GF2m_simple_mul() uses ec_wNAF_mul() if appropriate */ 433 * because ec_GF2m_simple_mul() uses ec_wNAF_mul() if appropriate */
384 434
385int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx) 435int
386 { 436ec_GF2m_precompute_mult(EC_GROUP * group, BN_CTX * ctx)
437{
387 return ec_wNAF_precompute_mult(group, ctx); 438 return ec_wNAF_precompute_mult(group, ctx);
388 } 439}
389 440
390int ec_GF2m_have_precompute_mult(const EC_GROUP *group) 441int
391 { 442ec_GF2m_have_precompute_mult(const EC_GROUP * group)
443{
392 return ec_wNAF_have_precompute_mult(group); 444 return ec_wNAF_have_precompute_mult(group);
393 } 445}
394 446
395#endif 447#endif