diff options
-rw-r--r-- | src/lib/libcrypto/ec/ec_mult.c | 120 |
1 files changed, 65 insertions, 55 deletions
diff --git a/src/lib/libcrypto/ec/ec_mult.c b/src/lib/libcrypto/ec/ec_mult.c index c33a033805..4944c34a1e 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.50 2024/11/23 07:37:21 tb Exp $ */ | 1 | /* $OpenBSD: ec_mult.c,v 1.51 2024/11/23 12:56:31 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 | */ |
@@ -61,7 +61,9 @@ | |||
61 | * and contributed to the OpenSSL project. | 61 | * and contributed to the OpenSSL project. |
62 | */ | 62 | */ |
63 | 63 | ||
64 | #include <stdint.h> | ||
64 | #include <stdlib.h> | 65 | #include <stdlib.h> |
66 | #include <string.h> | ||
65 | 67 | ||
66 | #include <openssl/bn.h> | 68 | #include <openssl/bn.h> |
67 | #include <openssl/ec.h> | 69 | #include <openssl/ec.h> |
@@ -160,15 +162,32 @@ ec_compute_wNAF(const BIGNUM *bn, signed char **out_wNAF, size_t *out_wNAF_len, | |||
160 | return ret; | 162 | return ret; |
161 | } | 163 | } |
162 | 164 | ||
165 | static void | ||
166 | free_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 | |||
163 | static int | 178 | static int |
164 | ec_compute_odd_multiples(const EC_GROUP *group, const EC_POINT *point, | 179 | ec_compute_odd_multiples(const EC_GROUP *group, const EC_POINT *point, |
165 | EC_POINT **row, size_t len, BN_CTX *ctx) | 180 | EC_POINT ***out_row, size_t row_len, BN_CTX *ctx) |
166 | { | 181 | { |
182 | EC_POINT **row = NULL; | ||
167 | EC_POINT *doubled = NULL; | 183 | EC_POINT *doubled = NULL; |
168 | size_t i; | 184 | size_t i; |
169 | int ret = 0; | 185 | int ret = 0; |
170 | 186 | ||
171 | if (len < 1) | 187 | if (row_len < 1) |
188 | goto err; | ||
189 | |||
190 | if ((row = calloc(row_len, sizeof(*row))) == NULL) | ||
172 | goto err; | 191 | goto err; |
173 | 192 | ||
174 | if ((row[0] = EC_POINT_dup(point, group)) == NULL) | 193 | if ((row[0] = EC_POINT_dup(point, group)) == NULL) |
@@ -178,84 +197,66 @@ ec_compute_odd_multiples(const EC_GROUP *group, const EC_POINT *point, | |||
178 | goto err; | 197 | goto err; |
179 | if (!EC_POINT_dbl(group, doubled, point, ctx)) | 198 | if (!EC_POINT_dbl(group, doubled, point, ctx)) |
180 | goto err; | 199 | goto err; |
181 | for (i = 1; i < len; i++) { | 200 | for (i = 1; i < row_len; i++) { |
182 | if ((row[i] = EC_POINT_new(group)) == NULL) | 201 | if ((row[i] = EC_POINT_new(group)) == NULL) |
183 | goto err; | 202 | goto err; |
184 | if (!EC_POINT_add(group, row[i], row[i - 1], doubled, ctx)) | 203 | if (!EC_POINT_add(group, row[i], row[i - 1], doubled, ctx)) |
185 | goto err; | 204 | goto err; |
186 | } | 205 | } |
187 | 206 | ||
207 | *out_row = row; | ||
208 | row = NULL; | ||
209 | |||
188 | ret = 1; | 210 | ret = 1; |
189 | 211 | ||
190 | err: | 212 | err: |
191 | EC_POINT_free(doubled); | 213 | EC_POINT_free(doubled); |
214 | free_row(row, row_len); | ||
192 | 215 | ||
193 | return ret; | 216 | return ret; |
194 | } | 217 | } |
195 | 218 | ||
196 | /* | 219 | /* |
197 | * This computes the wNAF representation of m and n and uses the window size to | 220 | * Compute the wNAF representation of m and a list of odd multiples of point. |
198 | * precompute the two rows of odd multiples of point and generator. On success, | ||
199 | * out_val owns the out_val_len points in the two rows. | ||
200 | * | ||
201 | * XXX - the only reason we need a single array is to be able to pass it to | ||
202 | * EC_POINTs_make_affine(). Consider writing a suitable variant that doesn't | ||
203 | * require such grotesque gymnastics. | ||
204 | */ | 221 | */ |
205 | 222 | ||
206 | static int | 223 | static int |
207 | ec_wNAF_precompute(const EC_GROUP *group, const BIGNUM *m, const EC_POINT *point, | 224 | ec_compute_row(const EC_GROUP *group, const BIGNUM *m, const EC_POINT *point, |
208 | const BIGNUM *n, signed char *wNAF[2], size_t wNAF_len[2], EC_POINT **row[2], | 225 | signed char **wNAF, size_t *wNAF_len, EC_POINT ***out_row, size_t *out_row_len, |
209 | EC_POINT ***out_val, size_t *out_val_len, 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 | |||
235 | static int | ||
236 | ec_normalize_rows(const EC_GROUP *group, EC_POINT **row0, size_t len0, | ||
237 | EC_POINT **row1, size_t len1, BN_CTX *ctx) | ||
210 | { | 238 | { |
211 | EC_POINT **val = NULL; | 239 | EC_POINT **val = NULL; |
212 | size_t val_len = 0; | 240 | size_t len = 0; |
213 | const EC_POINT *generator; | ||
214 | size_t len[2] = { 0 }; | ||
215 | size_t i; | ||
216 | int ret = 0; | 241 | int ret = 0; |
217 | 242 | ||
218 | *out_val = NULL; | 243 | if (len1 > SIZE_MAX - len0) |
219 | *out_val_len = 0; | ||
220 | |||
221 | if ((generator = EC_GROUP_get0_generator(group)) == NULL) { | ||
222 | ECerror(EC_R_UNDEFINED_GENERATOR); | ||
223 | goto err; | ||
224 | } | ||
225 | |||
226 | if (!ec_compute_wNAF(m, &wNAF[0], &wNAF_len[0], &len[0])) | ||
227 | goto err; | ||
228 | if (!ec_compute_wNAF(n, &wNAF[1], &wNAF_len[1], &len[1])) | ||
229 | goto err; | 244 | goto err; |
245 | len = len0 + len1; | ||
230 | 246 | ||
231 | if ((val = calloc(len[0] + len[1], sizeof(*val))) == NULL) { | 247 | if ((val = calloc(len, sizeof(*val))) == NULL) { |
232 | ECerror(ERR_R_MALLOC_FAILURE); | 248 | ECerror(ERR_R_MALLOC_FAILURE); |
233 | goto err; | 249 | goto err; |
234 | } | 250 | } |
235 | val_len = len[0] + len[1]; | 251 | memcpy(&val[0], row0, sizeof(*val) * len0); |
236 | 252 | memcpy(&val[len0], row1, sizeof(*val) * len1); | |
237 | row[0] = &val[0]; | ||
238 | row[1] = &val[len[0]]; | ||
239 | 253 | ||
240 | if (!ec_compute_odd_multiples(group, generator, row[0], len[0], ctx)) | 254 | if (!EC_POINTs_make_affine(group, len, val, ctx)) |
241 | goto err; | 255 | goto err; |
242 | if (!ec_compute_odd_multiples(group, point, row[1], len[1], ctx)) | ||
243 | goto err; | ||
244 | |||
245 | if (!EC_POINTs_make_affine(group, val_len, val, ctx)) | ||
246 | goto err; | ||
247 | |||
248 | *out_val = val; | ||
249 | val = NULL; | ||
250 | |||
251 | *out_val_len = val_len; | ||
252 | val_len = 0; | ||
253 | 256 | ||
254 | ret = 1; | 257 | ret = 1; |
255 | 258 | ||
256 | err: | 259 | err: |
257 | for (i = 0; i < val_len; i++) | ||
258 | EC_POINT_free(val[i]); | ||
259 | free(val); | 260 | free(val); |
260 | 261 | ||
261 | return ret; | 262 | return ret; |
@@ -269,11 +270,11 @@ int | |||
269 | ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *m, | 270 | ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *m, |
270 | const EC_POINT *point, const BIGNUM *n, BN_CTX *ctx) | 271 | const EC_POINT *point, const BIGNUM *n, BN_CTX *ctx) |
271 | { | 272 | { |
273 | const EC_POINT *generator; | ||
272 | signed char *wNAF[2] = { 0 }; | 274 | signed char *wNAF[2] = { 0 }; |
273 | size_t wNAF_len[2] = { 0 }; | 275 | size_t wNAF_len[2] = { 0 }; |
274 | EC_POINT **row[2] = { 0 }; | 276 | EC_POINT **row[2] = { 0 }; |
275 | EC_POINT **val = NULL; | 277 | size_t row_len[2] = { 0 }; |
276 | size_t val_len = 0; | ||
277 | size_t i; | 278 | size_t i; |
278 | int k; | 279 | int k; |
279 | int r_is_inverted = 0; | 280 | int r_is_inverted = 0; |
@@ -289,8 +290,18 @@ ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *m, | |||
289 | goto err; | 290 | goto err; |
290 | } | 291 | } |
291 | 292 | ||
292 | if (!ec_wNAF_precompute(group, m, point, n, wNAF, wNAF_len, row, | 293 | if ((generator = EC_GROUP_get0_generator(group)) == NULL) { |
293 | &val, &val_len, ctx)) | 294 | ECerror(EC_R_UNDEFINED_GENERATOR); |
295 | goto err; | ||
296 | } | ||
297 | |||
298 | if (!ec_compute_row(group, m, generator, &wNAF[0], &wNAF_len[0], | ||
299 | &row[0], &row_len[0], ctx)) | ||
300 | goto err; | ||
301 | if (!ec_compute_row(group, n, point, &wNAF[1], &wNAF_len[1], | ||
302 | &row[1], &row_len[1], ctx)) | ||
303 | goto err; | ||
304 | if (!ec_normalize_rows(group, row[0], row_len[0], row[1], row_len[1], ctx)) | ||
294 | goto err; | 305 | goto err; |
295 | 306 | ||
296 | max_len = wNAF_len[0]; | 307 | max_len = wNAF_len[0]; |
@@ -348,9 +359,8 @@ ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *m, | |||
348 | err: | 359 | err: |
349 | free(wNAF[0]); | 360 | free(wNAF[0]); |
350 | free(wNAF[1]); | 361 | free(wNAF[1]); |
351 | for (i = 0; i < val_len; i++) | 362 | free_row(row[0], row_len[0]); |
352 | EC_POINT_free(val[i]); | 363 | free_row(row[1], row_len[1]); |
353 | free(val); | ||
354 | 364 | ||
355 | return ret; | 365 | return ret; |
356 | } | 366 | } |