diff options
author | 2018-06-14 18:34:50 +0000 | |
---|---|---|
committer | 2018-06-14 18:34:50 +0000 | |
commit | e1190f3d42eeb5332f09e3c167a760938cb514de (patch) | |
tree | b1c9eda59e469d28807502f508d28ed171e888b1 | |
parent | Clarify the digest truncation comment in DSA signature generation. (diff) | |
download | wireguard-openbsd-e1190f3d42eeb5332f09e3c167a760938cb514de.tar.xz wireguard-openbsd-e1190f3d42eeb5332f09e3c167a760938cb514de.zip |
Use a blinding value when generating a DSA 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 tb@
-rw-r--r-- | lib/libcrypto/dsa/dsa_ossl.c | 48 |
1 files changed, 39 insertions, 9 deletions
diff --git a/lib/libcrypto/dsa/dsa_ossl.c b/lib/libcrypto/dsa/dsa_ossl.c index 2f7268839e9..c9399573abf 100644 --- a/lib/libcrypto/dsa/dsa_ossl.c +++ b/lib/libcrypto/dsa/dsa_ossl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dsa_ossl.c,v 1.36 2018/06/14 18:03:59 jsing Exp $ */ +/* $OpenBSD: dsa_ossl.c,v 1.37 2018/06/14 18:34:50 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -94,16 +94,17 @@ DSA_OpenSSL(void) static DSA_SIG * dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) { - BIGNUM *kinv = NULL, *r = NULL, *s = NULL; - BIGNUM m; - BIGNUM xr; + BIGNUM b, bm, bxr, binv, m, *kinv = NULL, *r = NULL, *s = NULL; BN_CTX *ctx = NULL; int reason = ERR_R_BN_LIB; DSA_SIG *ret = NULL; int noredo = 0; + BN_init(&b); + BN_init(&binv); + BN_init(&bm); + BN_init(&bxr); BN_init(&m); - BN_init(&xr); if (!dsa->p || !dsa->q || !dsa->g) { reason = DSA_R_MISSING_PARAMETERS; @@ -139,10 +140,36 @@ dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) noredo = 1; } - /* Compute s = inv(k) (m + xr) mod q */ - if (!BN_mod_mul(&xr, dsa->priv_key, r, dsa->q, ctx)) /* s = xr */ + /* + * Compute: + * + * s = inv(k)(m + xr) mod q + * + * In order to reduce the possibility of a side-channel attack, the + * following is calculated using a blinding value: + * + * s = inv(k)inv(b)(bm + bxr) mod q + * + * Where b is a random value in the range [1, q-1]. + */ + if (!BN_sub(&bm, dsa->q, BN_value_one())) + goto err; + if (!BN_rand_range(&b, &bm)) + goto err; + if (!BN_add(&b, &b, BN_value_one())) + goto err; + if (BN_mod_inverse_ct(&binv, &b, dsa->q, ctx) == NULL) + goto err; + + if (!BN_mod_mul(&bxr, &b, dsa->priv_key, dsa->q, ctx)) /* bx */ + goto err; + if (!BN_mod_mul(&bxr, &bxr, r, dsa->q, ctx)) /* bxr */ + goto err; + if (!BN_mod_mul(&bm, &b, &m, dsa->q, ctx)) /* bm */ + goto err; + if (!BN_mod_add(s, &bxr, &bm, dsa->q, ctx)) /* s = bm + bxr */ goto err; - if (!BN_mod_add(s, &xr, &m, dsa->q, ctx)) /* s = m + xr */ + if (!BN_mod_mul(s, s, &binv, dsa->q, ctx)) /* s = m + xr */ goto err; if (!BN_mod_mul(s, s, kinv, dsa->q, ctx)) goto err; @@ -173,8 +200,11 @@ dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) BN_free(s); } BN_CTX_free(ctx); + BN_clear_free(&b); + BN_clear_free(&bm); + BN_clear_free(&bxr); + BN_clear_free(&binv); BN_clear_free(&m); - BN_clear_free(&xr); BN_clear_free(kinv); return ret; |