diff options
author | tb <> | 2018-06-14 18:51:01 +0000 |
---|---|---|
committer | tb <> | 2018-06-14 18:51:01 +0000 |
commit | 419cc2003a828092974570e1c645b732b8908228 (patch) | |
tree | b0dafa4456b38f55ede9cb825ae6050bec87d29c /src/lib/libcrypto/ecdsa | |
parent | cc064d672d8fc76e2a66d1833709d38c5d72daaa (diff) | |
download | openbsd-419cc2003a828092974570e1c645b732b8908228.tar.gz openbsd-419cc2003a828092974570e1c645b732b8908228.tar.bz2 openbsd-419cc2003a828092974570e1c645b732b8908228.zip |
Use a blinding value when generating an ECDSA signature, in order to
reduce the possibility of a side-channel attack leaking the private key.
Suggested by Keegan Ryan at NCC Group.
With input from and ok jsing
Diffstat (limited to 'src/lib/libcrypto/ecdsa')
-rw-r--r-- | src/lib/libcrypto/ecdsa/ecs_ossl.c | 79 |
1 files changed, 65 insertions, 14 deletions
diff --git a/src/lib/libcrypto/ecdsa/ecs_ossl.c b/src/lib/libcrypto/ecdsa/ecs_ossl.c index 0f594aa86e..3939d7c8c1 100644 --- a/src/lib/libcrypto/ecdsa/ecs_ossl.c +++ b/src/lib/libcrypto/ecdsa/ecs_ossl.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ecs_ossl.c,v 1.11 2018/06/13 15:05:04 jsing Exp $ */ | 1 | /* $OpenBSD: ecs_ossl.c,v 1.12 2018/06/14 18:51:01 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Written by Nils Larsch for the OpenSSL project | 3 | * Written by Nils Larsch for the OpenSSL project |
4 | */ | 4 | */ |
@@ -221,14 +221,14 @@ static ECDSA_SIG * | |||
221 | ecdsa_do_sign(const unsigned char *dgst, int dgst_len, | 221 | ecdsa_do_sign(const unsigned char *dgst, int dgst_len, |
222 | const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey) | 222 | const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey) |
223 | { | 223 | { |
224 | int ok = 0, i; | 224 | BIGNUM *b = NULL, *binv = NULL, *bm = NULL, *bxr = NULL; |
225 | BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL, *order = NULL; | 225 | BIGNUM *kinv = NULL, *m = NULL, *order = NULL, *range = NULL, *s; |
226 | const BIGNUM *ckinv; | 226 | const BIGNUM *ckinv, *priv_key; |
227 | BN_CTX *ctx = NULL; | 227 | BN_CTX *ctx = NULL; |
228 | const EC_GROUP *group; | 228 | const EC_GROUP *group; |
229 | ECDSA_SIG *ret; | 229 | ECDSA_SIG *ret; |
230 | ECDSA_DATA *ecdsa; | 230 | ECDSA_DATA *ecdsa; |
231 | const BIGNUM *priv_key; | 231 | int ok = 0, i; |
232 | 232 | ||
233 | ecdsa = ecdsa_check(eckey); | 233 | ecdsa = ecdsa_check(eckey); |
234 | group = EC_KEY_get0_group(eckey); | 234 | group = EC_KEY_get0_group(eckey); |
@@ -247,7 +247,9 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, | |||
247 | s = ret->s; | 247 | s = ret->s; |
248 | 248 | ||
249 | if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL || | 249 | if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL || |
250 | (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) { | 250 | (range = BN_new()) == NULL || (b = BN_new()) == NULL || |
251 | (binv = BN_new()) == NULL || (bm = BN_new()) == NULL || | ||
252 | (bxr = BN_new()) == NULL || (m = BN_new()) == NULL) { | ||
251 | ECDSAerror(ERR_R_MALLOC_FAILURE); | 253 | ECDSAerror(ERR_R_MALLOC_FAILURE); |
252 | goto err; | 254 | goto err; |
253 | } | 255 | } |
@@ -286,11 +288,53 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, | |||
286 | } | 288 | } |
287 | } | 289 | } |
288 | 290 | ||
289 | if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) { | 291 | /* |
292 | * Compute s = inv(k)(m + xr) mod order. | ||
293 | * | ||
294 | * In order to reduce the possibility of a side-channel attack, | ||
295 | * the following is calculated using a blinding value: | ||
296 | * | ||
297 | * s = inv(k)inv(b)(bm + bxr) mod order | ||
298 | * | ||
299 | * where b is a random value in the range [1, order-1]. | ||
300 | */ | ||
301 | |||
302 | /* Generate b in range [1, order-1]. */ | ||
303 | if (!BN_sub(range, order, BN_value_one())) { | ||
304 | ECDSAerror(ERR_R_BN_LIB); | ||
305 | goto err; | ||
306 | } | ||
307 | if (!BN_rand_range(b, range)) { | ||
308 | ECDSAerror(ERR_R_BN_LIB); | ||
309 | goto err; | ||
310 | } | ||
311 | if (!BN_add(b, b, BN_value_one())) { | ||
312 | ECDSAerror(ERR_R_BN_LIB); | ||
313 | goto err; | ||
314 | } | ||
315 | |||
316 | if (BN_mod_inverse_ct(binv, b, order, ctx) == NULL) { | ||
317 | ECDSAerror(ERR_R_BN_LIB); | ||
318 | goto err; | ||
319 | } | ||
320 | |||
321 | if (!BN_mod_mul(bxr, b, priv_key, order, ctx)) { /* bx */ | ||
290 | ECDSAerror(ERR_R_BN_LIB); | 322 | ECDSAerror(ERR_R_BN_LIB); |
291 | goto err; | 323 | goto err; |
292 | } | 324 | } |
293 | if (!BN_mod_add(s, tmp, m, order, ctx)) { | 325 | if (!BN_mod_mul(bxr, bxr, ret->r, order, ctx)) { /* bxr */ |
326 | ECDSAerror(ERR_R_BN_LIB); | ||
327 | goto err; | ||
328 | } | ||
329 | if (!BN_mod_mul(bm, b, m, order, ctx)) { /* bm */ | ||
330 | ECDSAerror(ERR_R_BN_LIB); | ||
331 | goto err; | ||
332 | } | ||
333 | if (!BN_mod_add(s, bm, bxr, order, ctx)) { /* s = bm + bxr */ | ||
334 | ECDSAerror(ERR_R_BN_LIB); | ||
335 | goto err; | ||
336 | } | ||
337 | if (!BN_mod_mul(s, s, binv, order, ctx)) { /* s = m + xr */ | ||
294 | ECDSAerror(ERR_R_BN_LIB); | 338 | ECDSAerror(ERR_R_BN_LIB); |
295 | goto err; | 339 | goto err; |
296 | } | 340 | } |
@@ -298,9 +342,12 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, | |||
298 | ECDSAerror(ERR_R_BN_LIB); | 342 | ECDSAerror(ERR_R_BN_LIB); |
299 | goto err; | 343 | goto err; |
300 | } | 344 | } |
345 | |||
301 | if (BN_is_zero(s)) { | 346 | if (BN_is_zero(s)) { |
302 | /* if kinv and r have been supplied by the caller | 347 | /* |
303 | * don't to generate new kinv and r values */ | 348 | * If kinv and r have been supplied by the caller, |
349 | * don't generate new kinv and r values | ||
350 | */ | ||
304 | if (in_kinv != NULL && in_r != NULL) { | 351 | if (in_kinv != NULL && in_r != NULL) { |
305 | ECDSAerror(ECDSA_R_NEED_NEW_SETUP_VALUES); | 352 | ECDSAerror(ECDSA_R_NEED_NEW_SETUP_VALUES); |
306 | goto err; | 353 | goto err; |
@@ -318,10 +365,14 @@ err: | |||
318 | ret = NULL; | 365 | ret = NULL; |
319 | } | 366 | } |
320 | BN_CTX_free(ctx); | 367 | BN_CTX_free(ctx); |
368 | BN_clear_free(b); | ||
369 | BN_clear_free(binv); | ||
370 | BN_clear_free(bm); | ||
371 | BN_clear_free(bxr); | ||
372 | BN_clear_free(kinv); | ||
321 | BN_clear_free(m); | 373 | BN_clear_free(m); |
322 | BN_clear_free(tmp); | ||
323 | BN_free(order); | 374 | BN_free(order); |
324 | BN_clear_free(kinv); | 375 | BN_free(range); |
325 | return ret; | 376 | return ret; |
326 | } | 377 | } |
327 | 378 | ||