summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortb <>2019-09-29 10:09:09 +0000
committertb <>2019-09-29 10:09:09 +0000
commit64db159dc0c3a43dacf75ab5d2392b81db84b616 (patch)
tree7038bcba7697df93634b39c0eb7b52cbdc952be7 /src
parent6d64f4945aa38e327699e34de8fd7f86fdb0008b (diff)
downloadopenbsd-64db159dc0c3a43dacf75ab5d2392b81db84b616.tar.gz
openbsd-64db159dc0c3a43dacf75ab5d2392b81db84b616.tar.bz2
openbsd-64db159dc0c3a43dacf75ab5d2392b81db84b616.zip
If a NULL or zero cofactor is passed to EC_GROUP_set_generator(),
try to compute it using Hasse's bound. This works as long as the cofactor is small enough. Port of Brumley's fix for CVE-2019-1547 in OpenSSL 1.1.1 (old license) tests & ok inoguchi input & ok jsing commit 30c22fa8b1d840036b8e203585738df62a03cec8 Author: Billy Brumley <bbrumley@gmail.com> Date: Thu Sep 5 21:25:37 2019 +0300 [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 https://github.com/openssl/openssl/pull/9781)
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/ec/ec.h3
-rw-r--r--src/lib/libcrypto/ec/ec_err.c3
-rw-r--r--src/lib/libcrypto/ec/ec_lib.c118
3 files changed, 113 insertions, 11 deletions
diff --git a/src/lib/libcrypto/ec/ec.h b/src/lib/libcrypto/ec/ec.h
index d0e3673675..a95d99f6a9 100644
--- a/src/lib/libcrypto/ec/ec.h
+++ b/src/lib/libcrypto/ec/ec.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec.h,v 1.17 2019/09/06 17:59:25 jsing Exp $ */ 1/* $OpenBSD: ec.h,v 1.18 2019/09/29 10:09:09 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 */
@@ -1286,6 +1286,7 @@ void ERR_load_EC_strings(void);
1286#define EC_R_SLOT_FULL 108 1286#define EC_R_SLOT_FULL 108
1287#define EC_R_UNDEFINED_GENERATOR 113 1287#define EC_R_UNDEFINED_GENERATOR 113
1288#define EC_R_UNDEFINED_ORDER 128 1288#define EC_R_UNDEFINED_ORDER 128
1289#define EC_R_UNKNOWN_COFACTOR 164
1289#define EC_R_UNKNOWN_GROUP 129 1290#define EC_R_UNKNOWN_GROUP 129
1290#define EC_R_UNKNOWN_ORDER 114 1291#define EC_R_UNKNOWN_ORDER 114
1291#define EC_R_UNSUPPORTED_FIELD 131 1292#define EC_R_UNSUPPORTED_FIELD 131
diff --git a/src/lib/libcrypto/ec/ec_err.c b/src/lib/libcrypto/ec/ec_err.c
index 7c42618881..95c15a1110 100644
--- a/src/lib/libcrypto/ec/ec_err.c
+++ b/src/lib/libcrypto/ec/ec_err.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec_err.c,v 1.11 2019/09/06 17:59:25 jsing Exp $ */ 1/* $OpenBSD: ec_err.c,v 1.12 2019/09/29 10:09:09 tb Exp $ */
2/* ==================================================================== 2/* ====================================================================
3 * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved. 3 * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved.
4 * 4 *
@@ -124,6 +124,7 @@ static ERR_STRING_DATA EC_str_reasons[] =
124 {ERR_REASON(EC_R_SLOT_FULL), "slot full"}, 124 {ERR_REASON(EC_R_SLOT_FULL), "slot full"},
125 {ERR_REASON(EC_R_UNDEFINED_GENERATOR), "undefined generator"}, 125 {ERR_REASON(EC_R_UNDEFINED_GENERATOR), "undefined generator"},
126 {ERR_REASON(EC_R_UNDEFINED_ORDER), "undefined order"}, 126 {ERR_REASON(EC_R_UNDEFINED_ORDER), "undefined order"},
127 {ERR_REASON(EC_R_UNKNOWN_COFACTOR), "unknown cofactor"},
127 {ERR_REASON(EC_R_UNKNOWN_GROUP), "unknown group"}, 128 {ERR_REASON(EC_R_UNKNOWN_GROUP), "unknown group"},
128 {ERR_REASON(EC_R_UNKNOWN_ORDER), "unknown order"}, 129 {ERR_REASON(EC_R_UNKNOWN_ORDER), "unknown order"},
129 {ERR_REASON(EC_R_UNSUPPORTED_FIELD), "unsupported field"}, 130 {ERR_REASON(EC_R_UNSUPPORTED_FIELD), "unsupported field"},
diff --git a/src/lib/libcrypto/ec/ec_lib.c b/src/lib/libcrypto/ec/ec_lib.c
index e5d9620a00..df9061627e 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.31 2018/11/06 07:02:33 tb Exp $ */ 1/* $OpenBSD: ec_lib.c,v 1.32 2019/09/29 10:09:09 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 */
@@ -68,6 +68,7 @@
68#include <openssl/err.h> 68#include <openssl/err.h>
69#include <openssl/opensslv.h> 69#include <openssl/opensslv.h>
70 70
71#include "bn_lcl.h"
71#include "ec_lcl.h" 72#include "ec_lcl.h"
72 73
73/* functions for EC_GROUP objects */ 74/* functions for EC_GROUP objects */
@@ -252,6 +253,80 @@ EC_METHOD_get_field_type(const EC_METHOD *meth)
252 return meth->field_type; 253 return meth->field_type;
253} 254}
254 255
256/*
257 * Try computing the cofactor from generator order n and field cardinality q.
258 * This works for all curves of cryptographic interest.
259 *
260 * Hasse's theorem: | h * n - (q + 1) | <= 2 * sqrt(q)
261 *
262 * So: h_min = (q + 1 - 2*sqrt(q)) / n and h_max = (q + 1 + 2*sqrt(q)) / n and
263 * therefore h_max - h_min = 4*sqrt(q) / n. So if n > 4*sqrt(q) holds, there is
264 * only one possible value for h:
265 *
266 * h = \lfloor (h_min + h_max)/2 \rceil = \lfloor (q + 1)/n \rceil
267 *
268 * Otherwise, zero cofactor and return success.
269 */
270static int
271ec_guess_cofactor(EC_GROUP *group)
272{
273 BN_CTX *ctx = NULL;
274 BIGNUM *q = NULL;
275 int ret = 0;
276
277 /*
278 * If the cofactor is too large, we cannot guess it and default to zero.
279 * The RHS of below is a strict overestimate of log(4 * sqrt(q)).
280 */
281 if (BN_num_bits(&group->order) <=
282 (BN_num_bits(&group->field) + 1) / 2 + 3) {
283 BN_zero(&group->cofactor);
284 return 1;
285 }
286
287 if ((ctx = BN_CTX_new()) == NULL)
288 goto err;
289
290 BN_CTX_start(ctx);
291 if ((q = BN_CTX_get(ctx)) == NULL)
292 goto err;
293
294 /* Set q = 2**m for binary fields; q = p otherwise. */
295 if (group->meth->field_type == NID_X9_62_characteristic_two_field) {
296 BN_zero(q);
297 if (!BN_set_bit(q, BN_num_bits(&group->field) - 1))
298 goto err;
299 } else {
300 if (!BN_copy(q, &group->field))
301 goto err;
302 }
303
304 /*
305 * Compute
306 * h = \lfloor (q + 1)/n \rceil = \lfloor (q + 1 + n/2) / n \rfloor.
307 */
308
309 /* h = n/2 */
310 if (!BN_rshift1(&group->cofactor, &group->order))
311 goto err;
312 /* h = 1 + n/2 */
313 if (!BN_add(&group->cofactor, &group->cofactor, BN_value_one()))
314 goto err;
315 /* h = q + 1 + n/2 */
316 if (!BN_add(&group->cofactor, &group->cofactor, q))
317 goto err;
318 /* h = (q + 1 + n/2) / n */
319 if (!BN_div_ct(&group->cofactor, NULL, &group->cofactor, &group->order,
320 ctx))
321 goto err;
322
323 ret = 1;
324 err:
325 BN_CTX_end(ctx);
326 BN_CTX_free(ctx);
327 BN_zero(&group->cofactor);
328 return ret;
329}
255 330
256int 331int
257EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, 332EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
@@ -261,6 +336,33 @@ EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
261 ECerror(ERR_R_PASSED_NULL_PARAMETER); 336 ECerror(ERR_R_PASSED_NULL_PARAMETER);
262 return 0; 337 return 0;
263 } 338 }
339
340 /* Require group->field >= 1. */
341 if (BN_is_zero(&group->field) || BN_is_negative(&group->field)) {
342 ECerror(EC_R_INVALID_FIELD);
343 return 0;
344 }
345
346 /*
347 * Require order >= 1 and enforce an upper bound of at most one bit more
348 * than the field cardinality due to Hasse's theorem.
349 */
350 if (order == NULL || BN_is_zero(order) || BN_is_negative(order) ||
351 BN_num_bits(order) > BN_num_bits(&group->field) + 1) {
352 ECerror(EC_R_INVALID_GROUP_ORDER);
353 return 0;
354 }
355
356 /*
357 * Unfortunately, the cofactor is an optional field in many standards.
358 * Internally, the library uses a 0 cofactor as a marker for "unknown
359 * cofactor". So accept cofactor == NULL or cofactor >= 0.
360 */
361 if (cofactor != NULL && BN_is_negative(cofactor)) {
362 ECerror(EC_R_UNKNOWN_COFACTOR);
363 return 0;
364 }
365
264 if (group->generator == NULL) { 366 if (group->generator == NULL) {
265 group->generator = EC_POINT_new(group); 367 group->generator = EC_POINT_new(group);
266 if (group->generator == NULL) 368 if (group->generator == NULL)
@@ -269,17 +371,15 @@ EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
269 if (!EC_POINT_copy(group->generator, generator)) 371 if (!EC_POINT_copy(group->generator, generator))
270 return 0; 372 return 0;
271 373
272 if (order != NULL) { 374 if (!BN_copy(&group->order, order))
273 if (!BN_copy(&group->order, order)) 375 return 0;
274 return 0;
275 } else
276 BN_zero(&group->order);
277 376
278 if (cofactor != NULL) { 377 /* Either take the provided positive cofactor, or try to compute it. */
378 if (cofactor != NULL && !BN_is_zero(cofactor)) {
279 if (!BN_copy(&group->cofactor, cofactor)) 379 if (!BN_copy(&group->cofactor, cofactor))
280 return 0; 380 return 0;
281 } else 381 } else if (!ec_guess_cofactor(group))
282 BN_zero(&group->cofactor); 382 return 0;
283 383
284 return 1; 384 return 1;
285} 385}