summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortb <>2024-11-22 14:59:40 +0000
committertb <>2024-11-22 14:59:40 +0000
commitd25ca6829fcb33e9080bb5d7d5de5e01694d1cb7 (patch)
tree7790d27abad19186023db781852d4eb280ca3aa5 /src
parentaa15470973d1fcdb50d16c63b9cff3c9367ce30c (diff)
downloadopenbsd-d25ca6829fcb33e9080bb5d7d5de5e01694d1cb7.tar.gz
openbsd-d25ca6829fcb33e9080bb5d7d5de5e01694d1cb7.tar.bz2
openbsd-d25ca6829fcb33e9080bb5d7d5de5e01694d1cb7.zip
Split two helpers out of ec_wNAF_mul()
As its name indicates, the first, ec_compute_odd_multiples(), fills point, 3 * point, 5 * point, ..., (2 * len - 1) * point into row[]. In fact, it first computes doubled = 2 * point and then goes on to set row[i] = row[i - 1] + doubled. That's straightforward enough. One change here is that this helper allocates row[i] on the fly rather than preallocating the entire array of points up front. The second piece is the actual precomputation, ec_wNAF_precompute(). It first computes the wNAF digits of the two scalars n and m (in this order for now) with appropriate window size and length. Then the above mentioned val[] array is allocated and populated with odd multiples of point and generator. Finally, all points in val[] are made affine in a single step, which means we only need one modular inversion, and this then allows us to take fast paths in all the computations in the one remaining loop in ec_wNAF_mul(). ok jsing
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/ec/ec_mult.c211
1 files changed, 119 insertions, 92 deletions
diff --git a/src/lib/libcrypto/ec/ec_mult.c b/src/lib/libcrypto/ec/ec_mult.c
index 43fab4b83c..9a695a2fb6 100644
--- a/src/lib/libcrypto/ec/ec_mult.c
+++ b/src/lib/libcrypto/ec/ec_mult.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec_mult.c,v 1.41 2024/11/22 00:54:42 tb Exp $ */ 1/* $OpenBSD: ec_mult.c,v 1.42 2024/11/22 14:59:40 tb Exp $ */
2/* 2/*
3 * Originally written by Bodo Moeller and Nils Larsch for the OpenSSL project. 3 * Originally written by Bodo Moeller and Nils Larsch for the OpenSSL project.
4 */ 4 */
@@ -219,6 +219,113 @@ compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len)
219 (b) >= 20 ? 2 : \ 219 (b) >= 20 ? 2 : \
220 1)) 220 1))
221 221
222static int
223ec_compute_odd_multiples(const EC_GROUP *group, const EC_POINT *point,
224 EC_POINT **row, size_t len, BN_CTX *ctx)
225{
226 EC_POINT *doubled = NULL;
227 size_t i;
228 int ret = 0;
229
230 if (len < 1)
231 goto err;
232
233 if ((row[0] = EC_POINT_dup(point, group)) == NULL)
234 goto err;
235
236 if ((doubled = EC_POINT_new(group)) == NULL)
237 goto err;
238 if (!EC_POINT_dbl(group, doubled, point, ctx))
239 goto err;
240 for (i = 1; i < len; i++) {
241 if ((row[i] = EC_POINT_new(group)) == NULL)
242 goto err;
243 if (!EC_POINT_add(group, row[i], row[i - 1], doubled, ctx))
244 goto err;
245 }
246
247 ret = 1;
248
249 err:
250 EC_POINT_free(doubled);
251
252 return ret;
253}
254
255/*
256 * This computes the wNAF representation of m and n and uses the window size to
257 * precompute the two rows of odd multiples of point and generator. On success,
258 * out_val owns the out_val_len points in the two rows.
259 *
260 * XXX - the only reason we need a single array is to be able to pass it to
261 * EC_POINTs_make_affine(). Consider writing a suitable variant that doesn't
262 * require such grotesque gymnastics.
263 */
264
265static int
266ec_wNAF_precompute(const EC_GROUP *group, const BIGNUM *m, const EC_POINT *point,
267 const BIGNUM *n, signed char *wNAF[2], size_t wNAF_len[2], EC_POINT **row[2],
268 EC_POINT ***out_val, size_t *out_val_len, BN_CTX *ctx)
269{
270 EC_POINT **val = NULL;
271 size_t val_len = 0;
272 const EC_POINT *generator;
273 size_t wsize[2] = { 0 };
274 size_t i, len0, len1;
275 int ret = 0;
276
277 *out_val = NULL;
278 *out_val_len = 0;
279
280 if ((generator = EC_GROUP_get0_generator(group)) == NULL) {
281 ECerror(EC_R_UNDEFINED_GENERATOR);
282 goto err;
283 }
284
285 wsize[0] = EC_window_bits_for_scalar_size(BN_num_bits(n));
286 if ((wNAF[0] = compute_wNAF(n, wsize[0], &wNAF_len[0])) == NULL)
287 goto err;
288
289 wsize[1] = EC_window_bits_for_scalar_size(BN_num_bits(m));
290 if ((wNAF[1] = compute_wNAF(m, wsize[1], &wNAF_len[1])) == NULL)
291 goto err;
292
293 len0 = 1 << (wsize[0] - 1);
294 len1 = 1 << (wsize[1] - 1);
295
296 if ((val = calloc(len0 + len1, sizeof(*val))) == NULL) {
297 ECerror(ERR_R_MALLOC_FAILURE);
298 goto err;
299 }
300 val_len = len0 + len1;
301
302 row[0] = &val[0];
303 row[1] = &val[len0];
304
305 if (!ec_compute_odd_multiples(group, point, row[0], len0, ctx))
306 goto err;
307 if (!ec_compute_odd_multiples(group, generator, row[1], len1, ctx))
308 goto err;
309
310 if (!EC_POINTs_make_affine(group, val_len, val, ctx))
311 goto err;
312
313 *out_val = val;
314 val = NULL;
315
316 *out_val_len = val_len;
317 val_len = 0;
318
319 ret = 1;
320
321 err:
322 for (i = 0; i < val_len; i++)
323 EC_POINT_free(val[i]);
324 free(val);
325
326 return ret;
327}
328
222/* 329/*
223 * Compute r = generator * m + point * n in non-constant time. 330 * Compute r = generator * m + point * n in non-constant time.
224 */ 331 */
@@ -229,17 +336,13 @@ ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *m,
229{ 336{
230 signed char *wNAF[2] = { 0 }; 337 signed char *wNAF[2] = { 0 };
231 size_t wNAF_len[2] = { 0 }; 338 size_t wNAF_len[2] = { 0 };
232 size_t wsize[2] = { 0 };
233 const EC_POINT *generator = NULL;
234 EC_POINT *tmp = NULL;
235 EC_POINT **row[2] = { 0 }; 339 EC_POINT **row[2] = { 0 };
236 size_t i, j; 340 EC_POINT **val = NULL;
341 size_t val_len = 0;
342 size_t i;
237 int k; 343 int k;
238 int r_is_inverted = 0; 344 int r_is_inverted = 0;
239 size_t max_len = 0; 345 size_t max_len = 0;
240 size_t num_val;
241 EC_POINT **val = NULL; /* precomputation */
242 EC_POINT **v;
243 int ret = 0; 346 int ret = 0;
244 347
245 if (m == NULL || n == NULL) { 348 if (m == NULL || n == NULL) {
@@ -251,86 +354,13 @@ ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *m,
251 goto err; 354 goto err;
252 } 355 }
253 356
254 if ((generator = EC_GROUP_get0_generator(group)) == NULL) { 357 if (!ec_wNAF_precompute(group, m, point, n, wNAF, wNAF_len, row,
255 ECerror(EC_R_UNDEFINED_GENERATOR); 358 &val, &val_len, ctx))
256 goto err; 359 goto err;
257 }
258 360
259 /* num_val will be the total number of temporarily precomputed points */ 361 max_len = wNAF_len[0];
260 num_val = 0; 362 if (wNAF_len[1] > max_len)
261 363 max_len = wNAF_len[1];
262 for (i = 0; i < 2; i++) {
263 size_t bits;
264
265 bits = i < 1 ? BN_num_bits(n) : BN_num_bits(m);
266 wsize[i] = EC_window_bits_for_scalar_size(bits);
267 num_val += (size_t) 1 << (wsize[i] - 1);
268 wNAF[i] = compute_wNAF(i < 1 ? n : m, wsize[i], &wNAF_len[i]);
269 if (wNAF[i] == NULL)
270 goto err;
271 if (wNAF_len[i] > max_len)
272 max_len = wNAF_len[i];
273 }
274
275 /*
276 * All points we precompute now go into a single array 'val'.
277 * 'val_sub[i]' is a pointer to the subarray for the i-th point, or
278 * to a subarray of 'pre_comp->points' if we already have
279 * precomputation.
280 */
281 val = reallocarray(NULL, (num_val + 1), sizeof val[0]);
282 if (val == NULL) {
283 ECerror(ERR_R_MALLOC_FAILURE);
284 goto err;
285 }
286 val[num_val] = NULL; /* pivot element */
287
288 /* allocate points for precomputation */
289 v = val;
290 for (i = 0; i < 2; i++) {
291 row[i] = v;
292 for (j = 0; j < ((size_t) 1 << (wsize[i] - 1)); j++) {
293 *v = EC_POINT_new(group);
294 if (*v == NULL)
295 goto err;
296 v++;
297 }
298 }
299 if (!(v == val + num_val)) {
300 ECerror(ERR_R_INTERNAL_ERROR);
301 goto err;
302 }
303 if (!(tmp = EC_POINT_new(group)))
304 goto err;
305
306 /*
307 * prepare precomputed values:
308 * row[i][0] := points[i]
309 * row[i][1] := 3 * points[i]
310 * row[i][2] := 5 * points[i]
311 * ...
312 */
313 for (i = 0; i < 2; i++) {
314 if (i < 1) {
315 if (!EC_POINT_copy(row[i][0], point))
316 goto err;
317 } else {
318 if (!EC_POINT_copy(row[i][0], generator))
319 goto err;
320 }
321
322 if (wsize[i] > 1) {
323 if (!EC_POINT_dbl(group, tmp, row[i][0], ctx))
324 goto err;
325 for (j = 1; j < ((size_t) 1 << (wsize[i] - 1)); j++) {
326 if (!EC_POINT_add(group, row[i][j], row[i][j - 1], tmp, ctx))
327 goto err;
328 }
329 }
330 }
331
332 if (!EC_POINTs_make_affine(group, num_val, val, ctx))
333 goto err;
334 364
335 /* 365 /*
336 * Set r to the neutral element. Scan through the wNAF representations 366 * Set r to the neutral element. Scan through the wNAF representations
@@ -381,14 +411,11 @@ ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *m,
381 ret = 1; 411 ret = 1;
382 412
383 err: 413 err:
384 EC_POINT_free(tmp);
385 free(wNAF[0]); 414 free(wNAF[0]);
386 free(wNAF[1]); 415 free(wNAF[1]);
387 if (val != NULL) { 416 for (i = 0; i < val_len; i++)
388 for (v = val; *v != NULL; v++) 417 EC_POINT_free(val[i]);
389 EC_POINT_free(*v); 418 free(val);
390 free(val);
391 }
392 419
393 return ret; 420 return ret;
394} 421}