From 2a31983ef889138f6760e0a68e153bcc6d9f1913 Mon Sep 17 00:00:00 2001 From: David Shaw Date: Wed, 28 Jun 2006 17:12:55 +0000 Subject: [PATCH] * 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(). --- g10/ChangeLog | 6 ++++ g10/sign.c | 92 ++++++++++++++++++++++++--------------------------- 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index bb95f812a..239e244f6 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,5 +1,11 @@ 2006-06-28 David Shaw + * 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). diff --git a/g10/sign.c b/g10/sign.c index 39e39c633..830fa7495 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -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(hashlensk->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; } }