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