* sign.c (sign_file): When signing with multiple DSA keys, one being DSA1
authorDavid Shaw <dshaw@jabberwocky.com>
Wed, 28 Jun 2006 17:12:55 +0000 (17:12 +0000)
committerDavid Shaw <dshaw@jabberwocky.com>
Wed, 28 Jun 2006 17:12:55 +0000 (17:12 +0000)
and one being DSA2 and encrypting at the same time, if the recipient
preferences give a hash that can work with the DSA2 key, then allow the
DSA1 key to be promoted rather than giving up and using hash_for().

g10/ChangeLog
g10/sign.c

index bb95f81..239e244 100644 (file)
@@ -1,5 +1,11 @@
 2006-06-28  David Shaw  <dshaw@jabberwocky.com>
 
+       * sign.c (sign_file): When signing with multiple DSA keys, one
+       being DSA1 and one being DSA2 and encrypting at the same time, if
+       the recipient preferences give a hash that can work with the DSA2
+       key, then allow the DSA1 key to be promoted rather than giving up
+       and using hash_for().
+
        * pkclist.c (algo_available): Automatically enable DSA2 mode when
        handling a key that clearly isn't DSA1 (i.e. q!=160).
 
index 39e39c6..830fa74 100644 (file)
@@ -319,28 +319,6 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig,
       }
     else 
       {
-#if 0
-       /* Disabled for now.  It seems reasonable to accept a
-          truncated hash for a DSA1 key, even though we don't
-          generate it without --enable-dsa2.  Be liberal in what you
-          accept, etc. */
-
-       /* If it's a DSA key, and q is 160 bits, it might be an
-          old-style DSA key.  If the hash doesn't match the q, fail
-          unless --enable-dsa2 is set.  If the q isn't 160 bits, then
-          allow any hash since it must be a DSA2 key (if the hash is
-          too small, we'll fail in encode_md_value). */
-
-       if(sk->pubkey_algo==PUBKEY_ALGO_DSA
-          && (mpi_get_nbits(sk->skey[1])/8)==20
-          && !opt.flags.dsa2
-          && md_digest_length(digest_algo)!=20)
-         {
-           log_error(_("DSA requires the use of a 160 bit hash algorithm\n"));
-           return G10ERR_GENERAL;
-         }
-#endif
-
         frame = encode_md_value( NULL, sk, md, digest_algo );
         if (!frame)
           return G10ERR_GENERAL;
@@ -866,8 +844,13 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
     if (DBG_HASHING)
        md_start_debug (mfx.md, "sign");
 
-   /* If we're encrypting and signing, it is reasonable to pick the
-       hash algorithm to use out of the recepient key prefs. */
+    /* If we're encrypting and signing, it is reasonable to pick the
+       hash algorithm to use out of the recepient key prefs.  This is
+       best effort only, as in a DSA2 and smartcard world there are
+       cases where we cannot please everyone with a single hash (DSA2
+       wants >160 and smartcards want =160).  In the future this could
+       be more complex with different hashes for each sk, but the
+       current design requires a single hash for all SKs. */
     if(pk_list)
       {
        if(opt.def_digest_algo)
@@ -883,43 +866,54 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
          }
        else
          {
-           int hashlen=0,algo;
+           int hashlen=0,algo,smartcard=0;
 
            /* Of course, if the recipient asks for something
-              unreasonable (like a non-160-bit hash for DSA without
-              --enable-dsa2, for example), then don't do it.  Check
-              all sk's - if any are DSA, then the hash has
-              restrictions.  In the future this can be more complex
-              with different hashes for each sk, but so long as there
-              is only one signing algorithm with hash restrictions,
-              this is ok. -dms */
+              unreasonable (like the wrong hash for a DSA key) then
+              don't do it.  Check all sk's - if any are DSA or live
+              on a smartcard, then the hash has restrictions and we
+              may not be able to give the recipient what they want.
+              For DSA, pass a hint for the largest q we have.  Note
+              that this means that a q>160 key will override a q=160
+              key and force the use of truncation for the q=160 key.
+              The alternative would be to ignore the recipient prefs
+              completely and get a different hash for each DSA key in
+              hash_for().  The override behavior here is more or less
+              reasonable as it is under the control of the user which
+              keys they sign with for a given message and the fact
+              that the message with multiple signatures won't be
+              usable on an implementation that doesn't understand
+              DSA2 anyway. */
 
            for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next )
              {
                if(sk_rover->sk->pubkey_algo==PUBKEY_ALGO_DSA)
                  {
-                   if(opt.flags.dsa2)
-                     hashlen=mpi_get_nbits(sk_rover->sk->skey[1])/8;
-                   else
-                     hashlen=20;
-                   break;
+                   int temp_hashlen=mpi_get_nbits(sk_rover->sk->skey[1])/8;
+
+                   /* Pick a hash that is large enough for our
+                      largest q */
+
+                   if(hashlen<temp_hashlen)
+                     hashlen=temp_hashlen;
                  }
                else if(sk_rover->sk->is_protected
                        && sk_rover->sk->protect.s2k.mode==1002)
-                 {
-                   /* Current smartcards only do 160-bit hashes.
-                      Note that this may well have to change as the
-                      cards add algorithms. */
-
-                   hashlen=20;
-                   break;
-                 }
+                 smartcard=1;
              }
 
-           if((algo=
-               select_algo_from_prefs(pk_list,PREFTYPE_HASH,-1,
-                                      hashlen?&hashlen:NULL))>0)
-             recipient_digest_algo=algo;
+           /* Current smartcards only do 160-bit hashes.  If we have
+              to have a >160-bit hash, then we can't use the
+              recipient prefs as we'd need both =160 and >160 at the
+              same time and recipient prefs currently require a
+              single hash for all signatures.  All this may well have
+              to change as the cards add algorithms. */
+
+           if(!smartcard || (smartcard && hashlen==20))
+             if((algo=
+                 select_algo_from_prefs(pk_list,PREFTYPE_HASH,-1,
+                                        hashlen?&hashlen:NULL))>0)
+               recipient_digest_algo=algo;
          }
       }