Skip to content

Commit 30c22fa

Browse files
bbbrumleyromen
authored andcommitted
[crypto/ec] for ECC parameters with NULL or zero cofactor, compute it
The cofactor argument to EC_GROUP_set_generator is optional, and SCA mitigations for ECC currently use it. So the library currently falls back to very old SCA-vulnerable code if the cofactor is not present. This PR allows EC_GROUP_set_generator to compute the cofactor for all curves of cryptographic interest. Steering scalar multiplication to more SCA-robust code. This issue affects persisted private keys in explicit parameter form, where the (optional) cofactor field is zero or absent. It also affects curves not built-in to the library, but constructed programatically with explicit parameters, then calling EC_GROUP_set_generator with a nonsensical value (NULL, zero). The very old scalar multiplication code is known to be vulnerable to local uarch attacks, outside of the OpenSSL threat model. New results suggest the code path is also vulnerable to traditional wall clock timing attacks. CVE-2019-1547 Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org> Reviewed-by: Nicola Tuveri <nic.tuv@gmail.com> (Merged from #9781)
1 parent ed0ac11 commit 30c22fa

File tree

1 file changed

+96
-7
lines changed

1 file changed

+96
-7
lines changed

crypto/ec/ec_lib.c

Lines changed: 96 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,67 @@ int EC_METHOD_get_field_type(const EC_METHOD *meth)
265265

266266
static int ec_precompute_mont_data(EC_GROUP *);
267267

268+
/*-
269+
* Try computing cofactor from the generator order (n) and field cardinality (q).
270+
* This works for all curves of cryptographic interest.
271+
*
272+
* Hasse thm: q + 1 - 2*sqrt(q) <= n*h <= q + 1 + 2*sqrt(q)
273+
* h_min = (q + 1 - 2*sqrt(q))/n
274+
* h_max = (q + 1 + 2*sqrt(q))/n
275+
* h_max - h_min = 4*sqrt(q)/n
276+
* So if n > 4*sqrt(q) holds, there is only one possible value for h:
277+
* h = \lfloor (h_min + h_max)/2 \rceil = \lfloor (q + 1)/n \rceil
278+
*
279+
* Otherwise, zero cofactor and return success.
280+
*/
281+
static int ec_guess_cofactor(EC_GROUP *group) {
282+
int ret = 0;
283+
BN_CTX *ctx = NULL;
284+
BIGNUM *q = NULL;
285+
286+
/*-
287+
* If the cofactor is too large, we cannot guess it.
288+
* The RHS of below is a strict overestimate of lg(4 * sqrt(q))
289+
*/
290+
if (BN_num_bits(group->order) <= (BN_num_bits(group->field) + 1) / 2 + 3) {
291+
/* default to 0 */
292+
BN_zero(group->cofactor);
293+
/* return success */
294+
return 1;
295+
}
296+
297+
if ((ctx = BN_CTX_new()) == NULL)
298+
return 0;
299+
300+
BN_CTX_start(ctx);
301+
if ((q = BN_CTX_get(ctx)) == NULL)
302+
goto err;
303+
304+
/* set q = 2**m for binary fields; q = p otherwise */
305+
if (group->meth->field_type == NID_X9_62_characteristic_two_field) {
306+
BN_zero(q);
307+
if (!BN_set_bit(q, BN_num_bits(group->field) - 1))
308+
goto err;
309+
} else {
310+
if (!BN_copy(q, group->field))
311+
goto err;
312+
}
313+
314+
/* compute h = \lfloor (q + 1)/n \rceil = \lfloor (q + 1 + n/2)/n \rfloor */
315+
if (!BN_rshift1(group->cofactor, group->order) /* n/2 */
316+
|| !BN_add(group->cofactor, group->cofactor, q) /* q + n/2 */
317+
/* q + 1 + n/2 */
318+
|| !BN_add(group->cofactor, group->cofactor, BN_value_one())
319+
/* (q + 1 + n/2)/n */
320+
|| !BN_div(group->cofactor, NULL, group->cofactor, group->order, ctx))
321+
goto err;
322+
ret = 1;
323+
err:
324+
BN_CTX_end(ctx);
325+
BN_CTX_free(ctx);
326+
return ret;
327+
}
328+
268329
int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
269330
const BIGNUM *order, const BIGNUM *cofactor)
270331
{
@@ -273,6 +334,34 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
273334
return 0;
274335
}
275336

337+
/* require group->field >= 1 */
338+
if (group->field == NULL || BN_is_zero(group->field)
339+
|| BN_is_negative(group->field)) {
340+
ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_INVALID_FIELD);
341+
return 0;
342+
}
343+
344+
/*-
345+
* - require order >= 1
346+
* - enforce upper bound due to Hasse thm: order can be no more than one bit
347+
* longer than field cardinality
348+
*/
349+
if (order == NULL || BN_is_zero(order) || BN_is_negative(order)
350+
|| BN_num_bits(order) > BN_num_bits(group->field) + 1) {
351+
ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_INVALID_GROUP_ORDER);
352+
return 0;
353+
}
354+
355+
/*-
356+
* Unfortunately the cofactor is an optional field in many standards.
357+
* Internally, the lib uses 0 cofactor as a marker for "unknown cofactor".
358+
* So accept cofactor == NULL or cofactor >= 0.
359+
*/
360+
if (cofactor != NULL && BN_is_negative(cofactor)) {
361+
ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_UNKNOWN_COFACTOR);
362+
return 0;
363+
}
364+
276365
if (group->generator == NULL) {
277366
group->generator = EC_POINT_new(group);
278367
if (group->generator == NULL)
@@ -281,17 +370,17 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
281370
if (!EC_POINT_copy(group->generator, generator))
282371
return 0;
283372

284-
if (order != NULL) {
285-
if (!BN_copy(group->order, order))
286-
return 0;
287-
} else
288-
BN_zero(group->order);
373+
if (!BN_copy(group->order, order))
374+
return 0;
289375

290-
if (cofactor != NULL) {
376+
/* Either take the provided positive cofactor, or try to compute it */
377+
if (cofactor != NULL && !BN_is_zero(cofactor)) {
291378
if (!BN_copy(group->cofactor, cofactor))
292379
return 0;
293-
} else
380+
} else if (!ec_guess_cofactor(group)) {
294381
BN_zero(group->cofactor);
382+
return 0;
383+
}
295384

296385
/*
297386
* Some groups have an order with

0 commit comments

Comments
 (0)