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.
149 lines
4.8 KiB
149 lines
4.8 KiB
5 years ago
|
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;
|
||
|
+}
|