Blob Blame Raw
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;
+}