summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2023-06-20 14:37:15 +0000
committertb <>2023-06-20 14:37:15 +0000
commit08fb80ce5491017764657645ae3cbf1cb1dca3bd (patch)
tree7614c65770f638c15252aa105b307fcceb0a847d
parenta7641133988eb74a1505ddbdd5ef7d3cae70b041 (diff)
downloadopenbsd-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.c90
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 */
252static int 253static int
253ec_guess_cofactor(EC_GROUP *group) 254ec_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}