summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsing <jsing@openbsd.org>2018-06-14 18:34:50 +0000
committerjsing <jsing@openbsd.org>2018-06-14 18:34:50 +0000
commite1190f3d42eeb5332f09e3c167a760938cb514de (patch)
treeb1c9eda59e469d28807502f508d28ed171e888b1
parentClarify the digest truncation comment in DSA signature generation. (diff)
downloadwireguard-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.c48
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;