You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
148 lines
4.8 KiB
148 lines
4.8 KiB
diff -up openssl-1.0.2k/crypto/dsa/dsa_ossl.c.dsa-signing openssl-1.0.2k/crypto/dsa/dsa_ossl.c |
|
--- openssl-1.0.2k/crypto/dsa/dsa_ossl.c.dsa-signing 2019-02-08 10:53:17.825805336 +0100 |
|
+++ openssl-1.0.2k/crypto/dsa/dsa_ossl.c 2019-04-04 16:05:53.155386419 +0200 |
|
@@ -76,6 +76,8 @@ static int dsa_do_verify(const unsigned |
|
DSA_SIG *sig, DSA *dsa); |
|
static int dsa_init(DSA *dsa); |
|
static int dsa_finish(DSA *dsa); |
|
+static BIGNUM *dsa_mod_inverse_fermat(const BIGNUM *k, const BIGNUM *q, |
|
+ BN_CTX *ctx); |
|
|
|
static DSA_METHOD openssl_dsa_meth = { |
|
"OpenSSL DSA method", |
|
@@ -275,7 +277,9 @@ static int dsa_sign_setup(DSA *dsa, BN_C |
|
{ |
|
BN_CTX *ctx; |
|
BIGNUM k, kq, *K, *kinv = NULL, *r = NULL; |
|
+ BIGNUM l, m; |
|
int ret = 0; |
|
+ int q_bits; |
|
|
|
if (!dsa->p || !dsa->q || !dsa->g) { |
|
DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_MISSING_PARAMETERS); |
|
@@ -284,6 +288,8 @@ static int dsa_sign_setup(DSA *dsa, BN_C |
|
|
|
BN_init(&k); |
|
BN_init(&kq); |
|
+ BN_init(&l); |
|
+ BN_init(&m); |
|
|
|
if (ctx_in == NULL) { |
|
if ((ctx = BN_CTX_new()) == NULL) |
|
@@ -294,6 +300,13 @@ static int dsa_sign_setup(DSA *dsa, BN_C |
|
if ((r = BN_new()) == NULL) |
|
goto err; |
|
|
|
+ /* Preallocate space */ |
|
+ q_bits = BN_num_bits(dsa->q) + sizeof(dsa->q->d[0]) * 16; |
|
+ if (!BN_set_bit(&k, q_bits) |
|
+ || !BN_set_bit(&l, q_bits) |
|
+ || !BN_set_bit(&m, q_bits)) |
|
+ goto err; |
|
+ |
|
/* Get random k */ |
|
do |
|
if (!BN_rand_range(&k, dsa->q)) |
|
@@ -302,9 +315,9 @@ static int dsa_sign_setup(DSA *dsa, BN_C |
|
|
|
if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0) { |
|
BN_set_flags(&k, BN_FLG_CONSTTIME); |
|
+ BN_set_flags(&l, BN_FLG_CONSTTIME); |
|
} |
|
|
|
- |
|
if (dsa->flags & DSA_FLAG_CACHE_MONT_P) { |
|
if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p, |
|
CRYPTO_LOCK_DSA, dsa->p, ctx)) |
|
@@ -314,24 +327,23 @@ static int dsa_sign_setup(DSA *dsa, BN_C |
|
/* Compute r = (g^k mod p) mod q */ |
|
|
|
if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0) { |
|
- if (!BN_copy(&kq, &k)) |
|
- goto err; |
|
- |
|
- BN_set_flags(&kq, BN_FLG_CONSTTIME); |
|
- |
|
/* |
|
* We do not want timing information to leak the length of k, so we |
|
- * compute g^k using an equivalent exponent of fixed length. (This |
|
- * is a kludge that we need because the BN_mod_exp_mont() does not |
|
- * let us specify the desired timing behaviour.) |
|
+ * compute G^k using an equivalent scalar of fixed bit-length. |
|
+ * |
|
+ * We unconditionally perform both of these additions to prevent a |
|
+ * small timing information leakage. We then choose the sum that is |
|
+ * one bit longer than the modulus. |
|
+ * |
|
+ * TODO: revisit the BN_copy aiming for a memory access agnostic |
|
+ * conditional copy. |
|
*/ |
|
- |
|
- if (!BN_add(&kq, &kq, dsa->q)) |
|
+ if (!BN_add(&l, &k, dsa->q) |
|
+ || !BN_add(&m, &l, dsa->q) |
|
+ || !BN_copy(&kq, BN_num_bits(&l) > q_bits ? &l : &m)) |
|
goto err; |
|
- if (BN_num_bits(&kq) <= BN_num_bits(dsa->q)) { |
|
- if (!BN_add(&kq, &kq, dsa->q)) |
|
- goto err; |
|
- } |
|
+ |
|
+ BN_set_flags(&kq, BN_FLG_CONSTTIME); |
|
|
|
K = &kq; |
|
} else { |
|
@@ -343,8 +355,8 @@ static int dsa_sign_setup(DSA *dsa, BN_C |
|
if (!BN_mod(r, r, dsa->q, ctx)) |
|
goto err; |
|
|
|
- /* Compute part of 's = inv(k) (m + xr) mod q' */ |
|
- if ((kinv = BN_mod_inverse(NULL, &k, dsa->q, ctx)) == NULL) |
|
+ /* Compute part of 's = inv(k) (m + xr) mod q' */ |
|
+ if ((kinv = dsa_mod_inverse_fermat(&k, dsa->q, ctx)) == NULL) |
|
goto err; |
|
|
|
if (*kinvp != NULL) |
|
@@ -365,7 +377,9 @@ static int dsa_sign_setup(DSA *dsa, BN_C |
|
BN_CTX_free(ctx); |
|
BN_clear_free(&k); |
|
BN_clear_free(&kq); |
|
- return (ret); |
|
+ BN_clear_free(&l); |
|
+ BN_clear_free(&m); |
|
+ return ret; |
|
} |
|
|
|
static int dsa_do_verify(const unsigned char *dgst, int dgst_len, |
|
@@ -491,3 +505,31 @@ static int dsa_finish(DSA *dsa) |
|
BN_MONT_CTX_free(dsa->method_mont_p); |
|
return (1); |
|
} |
|
+ |
|
+/* |
|
+ * Compute the inverse of k modulo q. |
|
+ * Since q is prime, Fermat's Little Theorem applies, which reduces this to |
|
+ * mod-exp operation. Both the exponent and modulus are public information |
|
+ * so a mod-exp that doesn't leak the base is sufficient. A newly allocated |
|
+ * BIGNUM is returned which the caller must free. |
|
+ */ |
|
+static BIGNUM *dsa_mod_inverse_fermat(const BIGNUM *k, const BIGNUM *q, |
|
+ BN_CTX *ctx) |
|
+{ |
|
+ BIGNUM *res = NULL; |
|
+ BIGNUM *r, e; |
|
+ |
|
+ if ((r = BN_new()) == NULL) |
|
+ return NULL; |
|
+ |
|
+ BN_init(&e); |
|
+ |
|
+ if (BN_set_word(r, 2) |
|
+ && BN_sub(&e, q, r) |
|
+ && BN_mod_exp_mont(r, k, &e, q, ctx, NULL)) |
|
+ res = r; |
|
+ else |
|
+ BN_free(r); |
|
+ BN_free(&e); |
|
+ return res; |
|
+}
|
|
|