Avoid need to change function code.
[openssl.git] / crypto / dsa / dsa_ossl.c
index 38b4f06012c8dacb91d72cc0ac6a43e539492e87..edaee5987772b078b0f4274406c7e08f7486ed2f 100644 (file)
 #endif
 
 static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa);
-static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp);
+static int dsa_sign_setup_no_digest(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp);
+static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
+                                     BIGNUM **kinvp, BIGNUM **rp,
+                                     const unsigned char *dgst, int dlen);
 static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig,
                         DSA *dsa);
 static int dsa_init(DSA *dsa);
@@ -81,7 +84,7 @@ static int dsa_finish(DSA *dsa);
 static DSA_METHOD openssl_dsa_meth = {
 "OpenSSL DSA method",
 dsa_do_sign,
-dsa_sign_setup,
+dsa_sign_setup_no_digest,
 dsa_do_verify,
 NULL, /* dsa_mod_exp, */
 NULL, /* dsa_bn_mod_exp, */
@@ -176,7 +179,8 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
 redo:
        if ((dsa->kinv == NULL) || (dsa->r == NULL))
                {
-               if (!dsa->meth->dsa_sign_setup(dsa,ctx,&kinv,&r)) goto err;
+               if (!dsa_sign_setup(dsa,ctx,&kinv,&r,dgst,dlen))
+                       goto err;
                }
        else
                {
@@ -202,6 +206,7 @@ redo:
        if (BN_cmp(s,dsa->q) > 0)
                if (!BN_sub(s,s,dsa->q)) goto err;
        if (!BN_mod_mul(s,s,kinv,dsa->q,ctx)) goto err;
+
        ret=DSA_SIG_new();
        if (ret == NULL) goto err;
        /* Redo if r or s is zero as required by FIPS 186-3: this is
@@ -234,7 +239,14 @@ err:
        return(ret);
        }
 
-static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
+static int dsa_sign_setup_no_digest(DSA *dsa, BN_CTX *ctx_in,
+                         BIGNUM **kinvp, BIGNUM **rp) {
+       return dsa_sign_setup(dsa, ctx_in, kinvp, rp, NULL, 0);
+}
+
+static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
+                                     BIGNUM **kinvp, BIGNUM **rp,
+                                     const unsigned char *dgst, int dlen)
        {
        BN_CTX *ctx;
        BIGNUM k,kq,*K,*kinv=NULL,*r=NULL;
@@ -260,8 +272,22 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
 
        /* Get random k */
        do
-               if (!BN_rand_range(&k, dsa->q)) goto err;
-       while (BN_is_zero(&k));
+               {
+#ifndef OPENSSL_NO_SHA512
+               if (dgst != NULL)
+                       {
+                       /* We calculate k from SHA512(private_key + H(message)
+                        * + random). This protects the private key from a weak
+                        * PRNG. */
+                       if (!BN_generate_dsa_nonce(&k, dsa->q, dsa->priv_key, dgst,
+                                                  dlen, ctx))
+                               goto err;
+                       }
+               else
+#endif
+                       if (!BN_rand_range(&k, dsa->q)) goto err;
+               } while (BN_is_zero(&k));
+
        if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0)
                {
                BN_set_flags(&k, BN_FLG_CONSTTIME);