diff options
Diffstat (limited to '')
-rw-r--r-- | g10/ChangeLog | 21 | ||||
-rw-r--r-- | g10/Makefile.am | 2 | ||||
-rw-r--r-- | g10/gpg.c | 8 | ||||
-rw-r--r-- | g10/keydb.h | 13 | ||||
-rw-r--r-- | g10/parse-packet.c | 14 | ||||
-rw-r--r-- | g10/pkclist.c | 21 | ||||
-rw-r--r-- | g10/sign.c | 101 |
7 files changed, 115 insertions, 65 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog index 2fba9c488..7f204cde9 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,24 @@ +2006-07-27 Werner Koch <[email protected]> + + * parse-packet.c (parse_comment): Cap comments at 65k. + (parse_gpg_control): Skip too large control packets. + +2006-07-24 David Shaw <[email protected]> (wk) + + * keydb.h, pkclist.c (select_algo_from_prefs, algo_available): + Pass a union for preference hints rather than doing void * games. + + * sign.c (sign_file): Use it here. + + * 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). + 2006-06-30 Werner Koch <[email protected]> * misc.c (checksum_mpi): No need for nbits as they are alredy diff --git a/g10/Makefile.am b/g10/Makefile.am index fb54dd9f0..a9847cfa7 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -27,7 +27,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/gl -I$(top_srcdir)/common \ include $(top_srcdir)/am/cmacros.am -AM_CFLAGS = $(LIBGCRYPT_CFLAGS) -Wno-pointer-sign +AM_CFLAGS = $(LIBGCRYPT_CFLAGS) needed_libs = ../gl/libgnu.a ../common/libcommon.a ../jnlib/libjnlib.a @@ -357,7 +357,6 @@ enum cmd_and_opt_values oAllowMultisigVerification, oEnableDSA2, oDisableDSA2, - oDebugAllowRun, oNoop }; @@ -705,7 +704,6 @@ static ARGPARSE_OPTS opts[] = { { oAutoKeyLocate, "auto-key-locate", 2, "@"}, { oNoAutoKeyLocate, "no-auto-key-locate", 0, "@"}, - { oDebugAllowRun, "debug_allow_run", 0, "@"}, {0,NULL,0,NULL} }; @@ -1761,7 +1759,6 @@ main (int argc, char **argv ) int with_fpr = 0; /* make an option out of --fingerprint */ int any_explicit_recipient = 0; int require_secmem=0,got_secmem=0; - int allow_run = 0; #ifdef __riscos__ opt.lock_once = 1; @@ -2754,8 +2751,6 @@ main (int argc, char **argv ) case oEnableDSA2: opt.flags.dsa2=1; break; case oDisableDSA2: opt.flags.dsa2=0; break; - case oDebugAllowRun: allow_run = 1; break; - case oNoop: break; default : pargs.err = configfp? 1:2; break; @@ -2809,8 +2804,7 @@ main (int argc, char **argv ) } #endif - if (!allow_run) - log_fatal ("This version of gpg is not ready for use, use gpg 1.4.x\n"); + log_info ("WARNING: This version of gpg is not ready for use, use gpg 1.4.x\n"); /* FIXME: We should use logging to a file only in server mode; however we have not yet implemetyed that. Thus we try to get diff --git a/g10/keydb.h b/g10/keydb.h index f8be6efb9..2aab31cfa 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -144,6 +144,14 @@ struct keydb_search_desc { int exact; }; + +/* Helper type for preference fucntions. */ +union pref_hint +{ + int digest_length; +}; + + /*-- keydb.c --*/ /* @@ -175,9 +183,10 @@ void show_revocation_reason( PKT_public_key *pk, int mode ); int check_signatures_trust( PKT_signature *sig ); void release_pk_list( PK_LIST pk_list ); int build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ); -int algo_available( preftype_t preftype, int algo, void *hint ); +int algo_available( preftype_t preftype, int algo, + const union pref_hint *hint ); int select_algo_from_prefs( PK_LIST pk_list, int preftype, - int request, void *hint ); + int request, const union pref_hint *hint); int select_mdc_from_pklist (PK_LIST pk_list); /*-- skclist.c --*/ diff --git a/g10/parse-packet.c b/g10/parse-packet.c index d9a87f108..33472da4d 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -2147,6 +2147,16 @@ parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) { byte *p; + /* Cap comment packet at a reasonable value to avoid an integer + overflow in the malloc below. Comment packets are actually not + anymore define my OpenPGP and we even stopped to use our + private comment packet. */ + if (pktlen>65536) + { + log_error ("packet(%d) too large\n", pkttype); + iobuf_skip_rest (inp, pktlen, 0); + return G10ERR_INVALID_PACKET; + } packet->pkt.comment = xmalloc(sizeof *packet->pkt.comment + pktlen - 1); packet->pkt.comment->len = pktlen; p = packet->pkt.comment->data; @@ -2220,6 +2230,7 @@ parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, } mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--; namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--; + /* Note that namelen will never exceed 255 bytes. */ pt = pkt->pkt.plaintext = xmalloc(sizeof *pkt->pkt.plaintext + namelen -1); pt->new_ctb = new_ctb; pt->mode = mode; @@ -2399,6 +2410,9 @@ parse_gpg_control( IOBUF inp, int pkttype, if ( sesmark[i] != iobuf_get_noeof(inp) ) goto skipit; } + if (pktlen > 4096) + goto skipit; /* Definitely too large. We skip it to avoid an + overflow in the malloc. */ if ( list_mode ) puts ("- gpg control packet"); diff --git a/g10/pkclist.c b/g10/pkclist.c index d3cda144f..f90137aff 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -1186,7 +1186,7 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned int use ) preference list, so I'm including it. -dms */ int -algo_available( preftype_t preftype, int algo, void *hint ) +algo_available( preftype_t preftype, int algo, const union pref_hint *hint) { if( preftype == PREFTYPE_SYM ) { @@ -1210,18 +1210,18 @@ algo_available( preftype_t preftype, int algo, void *hint ) } else if( preftype == PREFTYPE_HASH ) { - if(hint) + if (hint && hint->digest_length) { - if(opt.flags.dsa2) + if (hint->digest_length!=20 || opt.flags.dsa2) { - /* If --enable-dsa2 is set, then we'll accept a hash - that is larger than we need. If --enable-dsa2 is not - set, then we won't accept any hash that isn't exactly - the right size. */ - if ((*(int *)hint) > gcry_md_get_algo_dlen (algo)) + /* If --enable-dsa2 is set or the hash isn't 160 bits + (which implies DSA2), then we'll accept a hash that + is larger than we need. Otherwise we won't accept + any hash that isn't exactly the right size. */ + if (hint->digest_length > gcry_md_get_algo_dlen (algo)) return 0; } - else if (((*(int *)hint) != gcry_md_get_algo_dlen (algo))) + else if (hint->digest_length != gcry_md_get_algo_dlen (algo)) return 0; } @@ -1259,7 +1259,8 @@ algo_available( preftype_t preftype, int algo, void *hint ) * Return -1 if we could not find an algorithm. */ int -select_algo_from_prefs(PK_LIST pk_list, int preftype, int request, void *hint) +select_algo_from_prefs(PK_LIST pk_list, int preftype, int request, + const union pref_hint *hint) { PK_LIST pkr; u32 bits[8]; diff --git a/g10/sign.c b/g10/sign.c index 0538f0020..7b6a81e10 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -320,27 +320,6 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig, } else { -#if 0 /* disabled *. - /* 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 - && (gcry_mpi_get_nbits (sk->skey[1])/8)==20 - && !opt.flags.dsa2 - && gcry_md_get_algo_dlen (digest_algo)!=20) - { - log_error(_("DSA requires the use of a 160 bit hash algorithm\n")); - return G10ERR_GENERAL; - } -#endif /* disabled */ - frame = encode_md_value( NULL, sk, md, digest_algo ); if (!frame) return G10ERR_GENERAL; @@ -869,8 +848,13 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, if (DBG_HASHING) gcry_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) @@ -886,30 +870,57 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, } else { - int hashlen=0,algo; + int algo, smartcard=0; + union pref_hint hint; + + hint.digest_length = 0; /* Of course, if the recipient asks for something - unreasonable (like a non-160-bit hash for DSA, for - example), then don't do it. Check all sk's - if any - are DSA, then the hash must be 160-bit. 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 */ - - /* Current smartcards only do 160-bit hashes as well. - Note that this may well have to change as the cards add - algorithms. */ - - for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) - if(sk_rover->sk->pubkey_algo==PUBKEY_ALGO_DSA - || (sk_rover->sk->is_protected - && sk_rover->sk->protect.s2k.mode==1002)) - hashlen=20; - - if((algo= - select_algo_from_prefs(pk_list,PREFTYPE_HASH,-1, - hashlen?&hashlen:NULL))>0) - recipient_digest_algo=algo; + 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) + { + int temp_hashlen = gcry_mpi_get_nbits + (sk_rover->sk->skey[1])+7/8; + + /* Pick a hash that is large enough for our + largest q */ + + if (hint.digest_length<temp_hashlen) + hint.digest_length=temp_hashlen; + } + else if (sk_rover->sk->is_protected + && sk_rover->sk->protect.s2k.mode == 1002) + smartcard = 1; + } + + /* 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 && hint.digest_length==20)) + if ( (algo= + select_algo_from_prefs(pk_list,PREFTYPE_HASH,-1,&hint)) > 0) + recipient_digest_algo=algo; } } |