summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/ec/ec_mult.c217
1 files changed, 131 insertions, 86 deletions
diff --git a/src/lib/libcrypto/ec/ec_mult.c b/src/lib/libcrypto/ec/ec_mult.c
index 4944c34a1e..0454a436a2 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.51 2024/11/23 12:56:31 tb Exp $ */ 1/* $OpenBSD: ec_mult.c,v 1.52 2024/12/06 15:39:59 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 */
@@ -71,6 +71,14 @@
71 71
72#include "ec_local.h" 72#include "ec_local.h"
73 73
74/* Holds the wNAF digits of bn and the corresponding odd multiples of point. */
75struct ec_wnaf {
76 signed char *digits;
77 size_t num_digits;
78 EC_POINT **multiples;
79 size_t num_multiples;
80};
81
74static int 82static int
75ec_window_bits(const BIGNUM *bn) 83ec_window_bits(const BIGNUM *bn)
76{ 84{
@@ -96,22 +104,18 @@ ec_window_bits(const BIGNUM *bn)
96 */ 104 */
97 105
98static int 106static int
99ec_compute_wNAF(const BIGNUM *bn, signed char **out_wNAF, size_t *out_wNAF_len, 107ec_compute_wnaf(const BIGNUM *bn, signed char *digits, size_t num_digits)
100 size_t *out_len)
101{ 108{
102 signed char *wNAF = NULL;
103 size_t i, wNAF_len, len;
104 int digit, bit, next, sign, wbits, window; 109 int digit, bit, next, sign, wbits, window;
110 size_t i;
105 int ret = 0; 111 int ret = 0;
106 112
107 wNAF_len = BN_num_bits(bn) + 1; 113 if (num_digits != BN_num_bits(bn) + 1) {
108 if ((wNAF = calloc(1, wNAF_len)) == NULL) { 114 ECerror(ERR_R_INTERNAL_ERROR);
109 ECerror(ERR_R_MALLOC_FAILURE);
110 goto err; 115 goto err;
111 } 116 }
112 117
113 wbits = ec_window_bits(bn); 118 wbits = ec_window_bits(bn);
114 len = 1 << (wbits - 1);
115 119
116 sign = BN_is_negative(bn) ? -1 : 1; 120 sign = BN_is_negative(bn) ? -1 : 1;
117 121
@@ -126,7 +130,7 @@ ec_compute_wNAF(const BIGNUM *bn, signed char **out_wNAF, size_t *out_wNAF_len,
126 } 130 }
127 131
128 /* Instead of bn >>= 1 in each iteration, slide window to the left. */ 132 /* Instead of bn >>= 1 in each iteration, slide window to the left. */
129 for (i = 0; i < wNAF_len; i++) { 133 for (i = 0; i < num_digits; i++) {
130 digit = 0; 134 digit = 0;
131 135
132 /* 136 /*
@@ -142,100 +146,64 @@ ec_compute_wNAF(const BIGNUM *bn, signed char **out_wNAF, size_t *out_wNAF_len,
142 window -= digit; 146 window -= digit;
143 } 147 }
144 148
145 wNAF[i] = sign * digit; 149 digits[i] = sign * digit;
146 150
147 /* Slide the window to the left. */ 151 /* Slide the window to the left. */
148 window >>= 1; 152 window >>= 1;
149 window += bit * BN_is_bit_set(bn, i + wbits + 1); 153 window += bit * BN_is_bit_set(bn, i + wbits + 1);
150 } 154 }
151 155
152 *out_wNAF = wNAF;
153 wNAF = NULL;
154 *out_wNAF_len = wNAF_len;
155 *out_len = len;
156
157 ret = 1; 156 ret = 1;
158 157
159 err: 158 err:
160 free(wNAF);
161
162 return ret; 159 return ret;
163} 160}
164 161
165static void
166free_row(EC_POINT **row, size_t row_len)
167{
168 size_t i;
169
170 if (row == NULL)
171 return;
172
173 for (i = 0; i < row_len; i++)
174 EC_POINT_free(row[i]);
175 free(row);
176}
177
178static int 162static int
179ec_compute_odd_multiples(const EC_GROUP *group, const EC_POINT *point, 163ec_compute_odd_multiples(const EC_GROUP *group, const EC_POINT *point,
180 EC_POINT ***out_row, size_t row_len, BN_CTX *ctx) 164 EC_POINT **multiples, size_t num_multiples, BN_CTX *ctx)
181{ 165{
182 EC_POINT **row = NULL;
183 EC_POINT *doubled = NULL; 166 EC_POINT *doubled = NULL;
184 size_t i; 167 size_t i;
185 int ret = 0; 168 int ret = 0;
186 169
187 if (row_len < 1) 170 if (num_multiples < 1)
188 goto err;
189
190 if ((row = calloc(row_len, sizeof(*row))) == NULL)
191 goto err; 171 goto err;
192 172
193 if ((row[0] = EC_POINT_dup(point, group)) == NULL) 173 if ((multiples[0] = EC_POINT_dup(point, group)) == NULL)
194 goto err; 174 goto err;
195 175
196 if ((doubled = EC_POINT_new(group)) == NULL) 176 if ((doubled = EC_POINT_new(group)) == NULL)
197 goto err; 177 goto err;
198 if (!EC_POINT_dbl(group, doubled, point, ctx)) 178 if (!EC_POINT_dbl(group, doubled, point, ctx))
199 goto err; 179 goto err;
200 for (i = 1; i < row_len; i++) { 180 for (i = 1; i < num_multiples; i++) {
201 if ((row[i] = EC_POINT_new(group)) == NULL) 181 if ((multiples[i] = EC_POINT_new(group)) == NULL)
202 goto err; 182 goto err;
203 if (!EC_POINT_add(group, row[i], row[i - 1], doubled, ctx)) 183 if (!EC_POINT_add(group, multiples[i], multiples[i - 1], doubled,
184 ctx))
204 goto err; 185 goto err;
205 } 186 }
206 187
207 *out_row = row;
208 row = NULL;
209
210 ret = 1; 188 ret = 1;
211 189
212 err: 190 err:
213 EC_POINT_free(doubled); 191 EC_POINT_free(doubled);
214 free_row(row, row_len);
215 192
216 return ret; 193 return ret;
217} 194}
218 195
219/* 196/*
220 * Compute the wNAF representation of m and a list of odd multiples of point. 197 * Bring multiples held in wnaf0 and wnaf1 simultaneously into affine form
198 * so that the operations in the loop in ec_wNAF_mul() can take fast paths.
221 */ 199 */
222 200
223static int 201static int
224ec_compute_row(const EC_GROUP *group, const BIGNUM *m, const EC_POINT *point, 202ec_normalize_points(const EC_GROUP *group, struct ec_wnaf *wnaf0,
225 signed char **wNAF, size_t *wNAF_len, EC_POINT ***out_row, size_t *out_row_len, 203 struct ec_wnaf *wnaf1, BN_CTX *ctx)
226 BN_CTX *ctx)
227{
228 if (!ec_compute_wNAF(m, wNAF, wNAF_len, out_row_len))
229 return 0;
230 if (!ec_compute_odd_multiples(group, point, out_row, *out_row_len, ctx))
231 return 0;
232 return 1;
233}
234
235static int
236ec_normalize_rows(const EC_GROUP *group, EC_POINT **row0, size_t len0,
237 EC_POINT **row1, size_t len1, BN_CTX *ctx)
238{ 204{
205 EC_POINT **points0 = wnaf0->multiples, **points1 = wnaf1->multiples;
206 size_t len0 = wnaf0->num_multiples, len1 = wnaf1->num_multiples;
239 EC_POINT **val = NULL; 207 EC_POINT **val = NULL;
240 size_t len = 0; 208 size_t len = 0;
241 int ret = 0; 209 int ret = 0;
@@ -248,8 +216,8 @@ ec_normalize_rows(const EC_GROUP *group, EC_POINT **row0, size_t len0,
248 ECerror(ERR_R_MALLOC_FAILURE); 216 ECerror(ERR_R_MALLOC_FAILURE);
249 goto err; 217 goto err;
250 } 218 }
251 memcpy(&val[0], row0, sizeof(*val) * len0); 219 memcpy(&val[0], points0, sizeof(*val) * len0);
252 memcpy(&val[len0], row1, sizeof(*val) * len1); 220 memcpy(&val[len0], points1, sizeof(*val) * len1);
253 221
254 if (!EC_POINTs_make_affine(group, len, val, ctx)) 222 if (!EC_POINTs_make_affine(group, len, val, ctx))
255 goto err; 223 goto err;
@@ -262,6 +230,88 @@ ec_normalize_rows(const EC_GROUP *group, EC_POINT **row0, size_t len0,
262 return ret; 230 return ret;
263} 231}
264 232
233static void
234ec_points_free(EC_POINT **points, size_t num_points)
235{
236 size_t i;
237
238 if (points == NULL)
239 return;
240
241 for (i = 0; i < num_points; i++)
242 EC_POINT_free(points[i]);
243 free(points);
244}
245
246static void
247ec_wnaf_free(struct ec_wnaf *wnaf)
248{
249 if (wnaf == NULL)
250 return;
251
252 free(wnaf->digits);
253 ec_points_free(wnaf->multiples, wnaf->num_multiples);
254 free(wnaf);
255}
256
257/*
258 * Calculate wNAF splitting of bn and the corresponding odd multiples of point.
259 */
260
261static struct ec_wnaf *
262ec_wnaf_new(const EC_GROUP *group, const EC_POINT *point, const BIGNUM *bn,
263 BN_CTX *ctx)
264{
265 struct ec_wnaf *wnaf;
266
267 if ((wnaf = calloc(1, sizeof(*wnaf))) == NULL)
268 goto err;
269
270 wnaf->num_digits = BN_num_bits(bn) + 1;
271 if ((wnaf->digits = calloc(wnaf->num_digits,
272 sizeof(*wnaf->digits))) == NULL)
273 goto err;
274
275 if (!ec_compute_wnaf(bn, wnaf->digits, wnaf->num_digits))
276 goto err;
277
278 wnaf->num_multiples = 1 << (ec_window_bits(bn) - 1);
279 if ((wnaf->multiples = calloc(wnaf->num_multiples,
280 sizeof(*wnaf->multiples))) == NULL)
281 goto err;
282
283 if (!ec_compute_odd_multiples(group, point, wnaf->multiples,
284 wnaf->num_multiples, ctx))
285 goto err;
286
287 return wnaf;
288
289 err:
290 ec_wnaf_free(wnaf);
291
292 return NULL;
293}
294
295static signed char
296ec_wnaf_digit(struct ec_wnaf *wnaf, size_t idx)
297{
298 if (idx >= wnaf->num_digits)
299 return 0;
300
301 return wnaf->digits[idx];
302}
303
304const EC_POINT *
305ec_wnaf_multiple(struct ec_wnaf *wnaf, signed char digit)
306{
307 if (digit < 0)
308 return NULL;
309 if (digit >= 2 * wnaf->num_multiples)
310 return NULL;
311
312 return wnaf->multiples[digit >> 1];
313}
314
265/* 315/*
266 * Compute r = generator * m + point * n in non-constant time. 316 * Compute r = generator * m + point * n in non-constant time.
267 */ 317 */
@@ -270,15 +320,12 @@ int
270ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *m, 320ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *m,
271 const EC_POINT *point, const BIGNUM *n, BN_CTX *ctx) 321 const EC_POINT *point, const BIGNUM *n, BN_CTX *ctx)
272{ 322{
323 struct ec_wnaf *wnaf[2] = { NULL, NULL };
273 const EC_POINT *generator; 324 const EC_POINT *generator;
274 signed char *wNAF[2] = { 0 };
275 size_t wNAF_len[2] = { 0 };
276 EC_POINT **row[2] = { 0 };
277 size_t row_len[2] = { 0 };
278 size_t i; 325 size_t i;
279 int k; 326 int k;
280 int r_is_inverted = 0; 327 int r_is_inverted = 0;
281 size_t max_len = 0; 328 size_t num_digits;
282 int ret = 0; 329 int ret = 0;
283 330
284 if (m == NULL || n == NULL) { 331 if (m == NULL || n == NULL) {
@@ -295,18 +342,17 @@ ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *m,
295 goto err; 342 goto err;
296 } 343 }
297 344
298 if (!ec_compute_row(group, m, generator, &wNAF[0], &wNAF_len[0], 345 if ((wnaf[0] = ec_wnaf_new(group, generator, m, ctx)) == NULL)
299 &row[0], &row_len[0], ctx))
300 goto err; 346 goto err;
301 if (!ec_compute_row(group, n, point, &wNAF[1], &wNAF_len[1], 347 if ((wnaf[1] = ec_wnaf_new(group, point, n, ctx)) == NULL)
302 &row[1], &row_len[1], ctx))
303 goto err; 348 goto err;
304 if (!ec_normalize_rows(group, row[0], row_len[0], row[1], row_len[1], ctx)) 349
350 if (!ec_normalize_points(group, wnaf[0], wnaf[1], ctx))
305 goto err; 351 goto err;
306 352
307 max_len = wNAF_len[0]; 353 num_digits = wnaf[0]->num_digits;
308 if (wNAF_len[1] > max_len) 354 if (wnaf[1]->num_digits > num_digits)
309 max_len = wNAF_len[1]; 355 num_digits = wnaf[1]->num_digits;
310 356
311 /* 357 /*
312 * Set r to the neutral element. Scan through the wNAF representations 358 * Set r to the neutral element. Scan through the wNAF representations
@@ -319,18 +365,16 @@ ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *m,
319 if (!EC_POINT_set_to_infinity(group, r)) 365 if (!EC_POINT_set_to_infinity(group, r))
320 goto err; 366 goto err;
321 367
322 for (k = max_len - 1; k >= 0; k--) { 368 for (k = num_digits - 1; k >= 0; k--) {
323 if (!EC_POINT_dbl(group, r, r, ctx)) 369 if (!EC_POINT_dbl(group, r, r, ctx))
324 goto err; 370 goto err;
325 371
326 for (i = 0; i < 2; i++) { 372 for (i = 0; i < 2; i++) {
327 int digit; 373 const EC_POINT *multiple;
374 signed char digit;
328 int is_neg = 0; 375 int is_neg = 0;
329 376
330 if (k >= wNAF_len[i]) 377 if ((digit = ec_wnaf_digit(wnaf[i], k)) == 0)
331 continue;
332
333 if ((digit = wNAF[i][k]) == 0)
334 continue; 378 continue;
335 379
336 if (digit < 0) { 380 if (digit < 0) {
@@ -344,7 +388,10 @@ ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *m,
344 r_is_inverted = !r_is_inverted; 388 r_is_inverted = !r_is_inverted;
345 } 389 }
346 390
347 if (!EC_POINT_add(group, r, r, row[i][digit >> 1], ctx)) 391 if ((multiple = ec_wnaf_multiple(wnaf[i], digit)) == NULL)
392 goto err;
393
394 if (!EC_POINT_add(group, r, r, multiple, ctx))
348 goto err; 395 goto err;
349 } 396 }
350 } 397 }
@@ -357,10 +404,8 @@ ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *m,
357 ret = 1; 404 ret = 1;
358 405
359 err: 406 err:
360 free(wNAF[0]); 407 ec_wnaf_free(wnaf[0]);
361 free(wNAF[1]); 408 ec_wnaf_free(wnaf[1]);
362 free_row(row[0], row_len[0]);
363 free_row(row[1], row_len[1]);
364 409
365 return ret; 410 return ret;
366} 411}