diff options
author | tb <> | 2023-06-20 14:37:15 +0000 |
---|---|---|
committer | tb <> | 2023-06-20 14:37:15 +0000 |
commit | 08fb80ce5491017764657645ae3cbf1cb1dca3bd (patch) | |
tree | 7614c65770f638c15252aa105b307fcceb0a847d | |
parent | a7641133988eb74a1505ddbdd5ef7d3cae70b041 (diff) | |
download | openbsd-08fb80ce5491017764657645ae3cbf1cb1dca3bd.tar.gz openbsd-08fb80ce5491017764657645ae3cbf1cb1dca3bd.tar.bz2 openbsd-08fb80ce5491017764657645ae3cbf1cb1dca3bd.zip |
Consolidate elliptic curve cofactor handling
The various checks of the cofactor to be set in EC_GROUP_set_generator()
are a bit all over the place. Move them into a single function and clean
things up a little. Instead of calculating directly with the cofactor
member of the group, use a temporary variable and copy this variable only
if all tests passed. In cryptographic contexts the cofactor almost always
fits if not into a single byte then into a word, so copying is cheap.
Also streamline the computations a bit and remove some binary curve
contortions.
ok jsing
-rw-r--r-- | src/lib/libcrypto/ec/ec_lib.c | 90 |
1 files changed, 41 insertions, 49 deletions
diff --git a/src/lib/libcrypto/ec/ec_lib.c b/src/lib/libcrypto/ec/ec_lib.c index 308a0f0061..817b0239be 100644 --- a/src/lib/libcrypto/ec/ec_lib.c +++ b/src/lib/libcrypto/ec/ec_lib.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ec_lib.c,v 1.57 2023/05/04 13:51:59 tb Exp $ */ | 1 | /* $OpenBSD: ec_lib.c,v 1.58 2023/06/20 14:37:15 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Originally written by Bodo Moeller for the OpenSSL project. | 3 | * Originally written by Bodo Moeller for the OpenSSL project. |
4 | */ | 4 | */ |
@@ -236,7 +236,8 @@ EC_METHOD_get_field_type(const EC_METHOD *meth) | |||
236 | } | 236 | } |
237 | 237 | ||
238 | /* | 238 | /* |
239 | * Try computing the cofactor from generator order n and field cardinality q. | 239 | * If there is a user-provided cofactor, sanity check and use it. Otherwise |
240 | * try computing the cofactor from generator order n and field cardinality q. | ||
240 | * This works for all curves of cryptographic interest. | 241 | * This works for all curves of cryptographic interest. |
241 | * | 242 | * |
242 | * Hasse's theorem: | h * n - (q + 1) | <= 2 * sqrt(q) | 243 | * Hasse's theorem: | h * n - (q + 1) | <= 2 * sqrt(q) |
@@ -250,56 +251,70 @@ EC_METHOD_get_field_type(const EC_METHOD *meth) | |||
250 | * Otherwise, zero cofactor and return success. | 251 | * Otherwise, zero cofactor and return success. |
251 | */ | 252 | */ |
252 | static int | 253 | static int |
253 | ec_guess_cofactor(EC_GROUP *group) | 254 | ec_set_cofactor(EC_GROUP *group, const BIGNUM *in_cofactor) |
254 | { | 255 | { |
255 | BN_CTX *ctx = NULL; | 256 | BN_CTX *ctx = NULL; |
256 | BIGNUM *q = NULL; | 257 | BIGNUM *cofactor; |
257 | int ret = 0; | 258 | int ret = 0; |
258 | 259 | ||
259 | /* | 260 | BN_zero(&group->cofactor); |
260 | * If the cofactor is too large, we cannot guess it and default to zero. | ||
261 | * The RHS of below is a strict overestimate of log(4 * sqrt(q)). | ||
262 | */ | ||
263 | if (BN_num_bits(&group->order) <= | ||
264 | (BN_num_bits(&group->field) + 1) / 2 + 3) { | ||
265 | BN_zero(&group->cofactor); | ||
266 | return 1; | ||
267 | } | ||
268 | 261 | ||
269 | if ((ctx = BN_CTX_new()) == NULL) | 262 | if ((ctx = BN_CTX_new()) == NULL) |
270 | goto err; | 263 | goto err; |
271 | 264 | ||
272 | BN_CTX_start(ctx); | 265 | BN_CTX_start(ctx); |
273 | if ((q = BN_CTX_get(ctx)) == NULL) | 266 | if ((cofactor = BN_CTX_get(ctx)) == NULL) |
274 | goto err; | 267 | goto err; |
275 | 268 | ||
276 | /* Set q = 2**m for binary fields; q = p otherwise. */ | 269 | /* |
277 | if (group->meth->field_type == NID_X9_62_characteristic_two_field) { | 270 | * Unfortunately, the cofactor is an optional field in many standards. |
278 | BN_zero(q); | 271 | * Internally, the library uses a 0 cofactor as a marker for "unknown |
279 | if (!BN_set_bit(q, BN_num_bits(&group->field) - 1)) | 272 | * cofactor". So accept in_cofactor == NULL or in_cofactor >= 0. |
273 | */ | ||
274 | if (in_cofactor != NULL && !BN_is_zero(in_cofactor)) { | ||
275 | if (BN_is_negative(in_cofactor)) { | ||
276 | ECerror(EC_R_UNKNOWN_COFACTOR); | ||
280 | goto err; | 277 | goto err; |
281 | } else { | 278 | } |
282 | if (!bn_copy(q, &group->field)) | 279 | if (!bn_copy(cofactor, in_cofactor)) |
283 | goto err; | 280 | goto err; |
281 | goto done; | ||
284 | } | 282 | } |
285 | 283 | ||
286 | /* | 284 | /* |
285 | * If the cofactor is too large, we cannot guess it and default to zero. | ||
286 | * The RHS of below is a strict overestimate of log(4 * sqrt(q)). | ||
287 | */ | ||
288 | if (BN_num_bits(&group->order) <= | ||
289 | (BN_num_bits(&group->field) + 1) / 2 + 3) | ||
290 | goto done; | ||
291 | |||
292 | /* | ||
287 | * Compute | 293 | * Compute |
288 | * h = \lfloor (q + 1)/n \rceil = \lfloor (q + 1 + n/2) / n \rfloor. | 294 | * h = \lfloor (q + 1)/n \rceil = \lfloor (q + 1 + n/2) / n \rfloor. |
289 | */ | 295 | */ |
290 | 296 | ||
291 | /* h = n/2 */ | 297 | /* h = n/2 */ |
292 | if (!BN_rshift1(&group->cofactor, &group->order)) | 298 | if (!BN_rshift1(cofactor, &group->order)) |
293 | goto err; | 299 | goto err; |
294 | /* h = 1 + n/2 */ | 300 | /* h = 1 + n/2 */ |
295 | if (!BN_add(&group->cofactor, &group->cofactor, BN_value_one())) | 301 | if (!BN_add_word(cofactor, 1)) |
296 | goto err; | 302 | goto err; |
297 | /* h = q + 1 + n/2 */ | 303 | /* h = q + 1 + n/2 */ |
298 | if (!BN_add(&group->cofactor, &group->cofactor, q)) | 304 | if (!BN_add(cofactor, cofactor, &group->field)) |
299 | goto err; | 305 | goto err; |
300 | /* h = (q + 1 + n/2) / n */ | 306 | /* h = (q + 1 + n/2) / n */ |
301 | if (!BN_div_ct(&group->cofactor, NULL, &group->cofactor, &group->order, | 307 | if (!BN_div_ct(cofactor, NULL, cofactor, &group->order, ctx)) |
302 | ctx)) | 308 | goto err; |
309 | |||
310 | done: | ||
311 | /* Use Hasse's theorem to bound the cofactor. */ | ||
312 | if (BN_num_bits(cofactor) > BN_num_bits(&group->field) + 1) { | ||
313 | ECerror(EC_R_INVALID_GROUP_ORDER); | ||
314 | goto err; | ||
315 | } | ||
316 | |||
317 | if (!bn_copy(&group->cofactor, cofactor)) | ||
303 | goto err; | 318 | goto err; |
304 | 319 | ||
305 | ret = 1; | 320 | ret = 1; |
@@ -308,9 +323,6 @@ ec_guess_cofactor(EC_GROUP *group) | |||
308 | BN_CTX_end(ctx); | 323 | BN_CTX_end(ctx); |
309 | BN_CTX_free(ctx); | 324 | BN_CTX_free(ctx); |
310 | 325 | ||
311 | if (ret != 1) | ||
312 | BN_zero(&group->cofactor); | ||
313 | |||
314 | return ret; | 326 | return ret; |
315 | } | 327 | } |
316 | 328 | ||
@@ -339,16 +351,6 @@ EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, | |||
339 | return 0; | 351 | return 0; |
340 | } | 352 | } |
341 | 353 | ||
342 | /* | ||
343 | * Unfortunately, the cofactor is an optional field in many standards. | ||
344 | * Internally, the library uses a 0 cofactor as a marker for "unknown | ||
345 | * cofactor". So accept cofactor == NULL or cofactor >= 0. | ||
346 | */ | ||
347 | if (cofactor != NULL && BN_is_negative(cofactor)) { | ||
348 | ECerror(EC_R_UNKNOWN_COFACTOR); | ||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | if (group->generator == NULL) { | 354 | if (group->generator == NULL) { |
353 | group->generator = EC_POINT_new(group); | 355 | group->generator = EC_POINT_new(group); |
354 | if (group->generator == NULL) | 356 | if (group->generator == NULL) |
@@ -360,18 +362,8 @@ EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, | |||
360 | if (!bn_copy(&group->order, order)) | 362 | if (!bn_copy(&group->order, order)) |
361 | return 0; | 363 | return 0; |
362 | 364 | ||
363 | /* Either take the provided positive cofactor, or try to compute it. */ | 365 | if (!ec_set_cofactor(group, cofactor)) |
364 | if (cofactor != NULL && !BN_is_zero(cofactor)) { | ||
365 | if (!bn_copy(&group->cofactor, cofactor)) | ||
366 | return 0; | ||
367 | } else if (!ec_guess_cofactor(group)) | ||
368 | return 0; | ||
369 | |||
370 | /* Use Hasse's theorem to bound the cofactor. */ | ||
371 | if (BN_num_bits(&group->cofactor) > BN_num_bits(&group->field) + 1) { | ||
372 | ECerror(EC_R_INVALID_GROUP_ORDER); | ||
373 | return 0; | 366 | return 0; |
374 | } | ||
375 | 367 | ||
376 | return 1; | 368 | return 1; |
377 | } | 369 | } |