1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-21 01:02:46 +02:00

* options.h, gpg.c (main): Add --enable-dsa2 and --disable-dsa2. Defaults

to disable.

* pkclist.c (algo_available): If --enable-dsa2 is set, we're allowed to
truncate hashes to fit DSA keys.

* sign.c (match_dsa_hash): New.  Return the best match hash for a given q
size. (do_sign, hash_for, sign_file): When signing with a DSA key, if it
has q==160, assume it is an old DSA key and don't allow truncation unless
--enable-dsa2 is also set.  q!=160 always allows truncation since they
must be DSA2 keys. (make_keysig_packet): If the user doesn't specify a
--cert-digest-algo, use match_dsa_hash to pick the best hash for key
signatures.
This commit is contained in:
David Shaw 2006-04-20 21:32:42 +00:00
parent b625a6d1a9
commit 0f1c0a9f28
5 changed files with 145 additions and 34 deletions

View File

@ -1,3 +1,21 @@
2006-04-20 David Shaw <dshaw@jabberwocky.com>
* options.h, gpg.c (main): Add --enable-dsa2 and --disable-dsa2.
Defaults to disable.
* pkclist.c (algo_available): If --enable-dsa2 is set, we're
allowed to truncate hashes to fit DSA keys.
* sign.c (match_dsa_hash): New. Return the best match hash for a
given q size.
(do_sign, hash_for, sign_file): When signing with a DSA key, if it
has q==160, assume it is an old DSA key and don't allow truncation
unless --enable-dsa2 is also set. q!=160 always allows truncation
since they must be DSA2 keys.
(make_keysig_packet): If the user doesn't specify a
--cert-digest-algo, use match_dsa_hash to pick the best hash for
key signatures.
2006-04-19 David Shaw <dshaw@jabberwocky.com> 2006-04-19 David Shaw <dshaw@jabberwocky.com>
* gpg.c (print_mds), armor.c (armor_filter, parse_hash_header): * gpg.c (print_mds), armor.c (armor_filter, parse_hash_header):

View File

@ -362,6 +362,8 @@ enum cmd_and_opt_values
oAutoKeyLocate, oAutoKeyLocate,
oNoAutoKeyLocate, oNoAutoKeyLocate,
oAllowMultisigVerification, oAllowMultisigVerification,
oEnableDSA2,
oDisableDSA2,
oNoop oNoop
}; };
@ -699,6 +701,8 @@ static ARGPARSE_OPTS opts[] = {
{ oDebugCCIDDriver, "debug-ccid-driver", 0, "@"}, { oDebugCCIDDriver, "debug-ccid-driver", 0, "@"},
#endif #endif
{ oAllowMultisigVerification, "allow-multisig-verification", 0, "@"}, { oAllowMultisigVerification, "allow-multisig-verification", 0, "@"},
{ oEnableDSA2, "enable-dsa2", 0, "@"},
{ oDisableDSA2, "disable-dsa2", 0, "@"},
/* These two are aliases to help users of the PGP command line /* These two are aliases to help users of the PGP command line
product use gpg with minimal pain. Many commands are common product use gpg with minimal pain. Many commands are common
@ -2659,6 +2663,9 @@ main (int argc, char **argv )
opt.allow_multisig_verification = 1; opt.allow_multisig_verification = 1;
break; break;
case oEnableDSA2: opt.flags.dsa2=1; break;
case oDisableDSA2: opt.flags.dsa2=0; break;
case oNoop: break; case oNoop: break;
default : pargs.err = configfp? 1:2; break; default : pargs.err = configfp? 1:2; break;

View File

@ -222,6 +222,7 @@ struct
unsigned int require_cross_cert:1; unsigned int require_cross_cert:1;
unsigned int use_embedded_filename:1; unsigned int use_embedded_filename:1;
unsigned int utf8_filename:1; unsigned int utf8_filename:1;
unsigned int dsa2:1;
} flags; } flags;
/* Linked list of ways to find a key if the key isn't on the local /* Linked list of ways to find a key if the key isn't on the local

View File

@ -1,6 +1,6 @@
/* pkclist.c /* pkclist.c
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
* 2004, 2005 Free Software Foundation, Inc. * 2006 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -1210,8 +1210,20 @@ algo_available( preftype_t preftype, int algo, void *hint )
} }
else if( preftype == PREFTYPE_HASH ) else if( preftype == PREFTYPE_HASH )
{ {
if(hint && ((*(int *)hint) != md_digest_length(algo))) if(hint)
return 0; {
if(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) > md_digest_length(algo))
return 0;
}
else if(((*(int *)hint) != md_digest_length(algo)))
return 0;
}
if((PGP6 || PGP7) && (algo != DIGEST_ALGO_MD5 if((PGP6 || PGP7) && (algo != DIGEST_ALGO_MD5
&& algo != DIGEST_ALGO_SHA1 && algo != DIGEST_ALGO_SHA1

View File

@ -319,10 +319,15 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig,
} }
else else
{ {
/* TODO: remove this check in the future once all the /* If it's a DSA key, and q is 160 bits, it might be an
variable-q DSA stuff makes it into the standard. */ old-style DSA key. If the hash doesn't match the q, fail
if(!opt.expert unless --enable-dsa2 is set. If the q isn't 160 bits, then
&& sk->pubkey_algo==PUBKEY_ALGO_DSA 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) && md_digest_length(digest_algo)!=20)
{ {
log_error(_("DSA requires the use of a 160 bit hash algorithm\n")); log_error(_("DSA requires the use of a 160 bit hash algorithm\n"));
@ -384,6 +389,29 @@ complete_sig( PKT_signature *sig, PKT_secret_key *sk, MD_HANDLE md )
return rc; return rc;
} }
static int
match_dsa_hash(unsigned int qbytes)
{
if(qbytes<=20)
return DIGEST_ALGO_SHA1;
#ifdef USE_SHA256
if(qbytes<=28)
return DIGEST_ALGO_SHA224;
if(qbytes<=32)
return DIGEST_ALGO_SHA256;
#endif
#ifdef USE_SHA512
if(qbytes<=48)
return DIGEST_ALGO_SHA384;
if(qbytes<=64)
return DIGEST_ALGO_SHA512;
#endif
return DEFAULT_DIGEST_ALGO;
/* DEFAULT_DIGEST_ALGO will certainly fail, but it's the best wrong
answer we have if the larger SHAs aren't there. */
}
/* /*
First try --digest-algo. If that isn't set, see if the recipient First try --digest-algo. If that isn't set, see if the recipient
has a preferred algorithm (which is also filtered through has a preferred algorithm (which is also filtered through
@ -405,21 +433,50 @@ hash_for(PKT_secret_key *sk)
return opt.def_digest_algo; return opt.def_digest_algo;
else if( recipient_digest_algo ) else if( recipient_digest_algo )
return recipient_digest_algo; return recipient_digest_algo;
else if(sk->pubkey_algo==PUBKEY_ALGO_DSA else if(sk->pubkey_algo==PUBKEY_ALGO_DSA)
|| (sk->is_protected && sk->protect.s2k.mode==1002))
{ {
/* The sk lives on a smartcard, or it's a DSA key. DSA requires unsigned int qbytes=mpi_get_nbits(sk->skey[1])/8;
a 160-bit hash, and current smartcards only handle SHA-1 and
RIPEMD/160 (i.e. 160-bit hashes). This is correct now, but /* It's a DSA key, so find a hash that is the same size as q or
may need revision as the cards add algorithms and/or DSA is larger. If q is 160, assume it is an old DSA key and use a
expanded to use larger hashes. */ 160-bit hash unless --enable-dsa2 is set, in which case act
like a new DSA key that just happens to have a 160-bit q
(i.e. allow truncation). If q is not 160, by definition it
must be a new DSA key. */
if(opt.personal_digest_prefs)
{
prefitem_t *prefs;
if(qbytes!=20 || opt.flags.dsa2)
{
for(prefs=opt.personal_digest_prefs;prefs->type;prefs++)
if(md_digest_length(prefs->value)>=qbytes)
return prefs->value;
}
else
{
for(prefs=opt.personal_digest_prefs;prefs->type;prefs++)
if(md_digest_length(prefs->value)==qbytes)
return prefs->value;
}
}
return match_dsa_hash(qbytes);
}
else if(sk->is_protected && sk->protect.s2k.mode==1002)
{
/* The sk lives on a smartcard, and current smartcards only
handle SHA-1 and RIPEMD/160. This is correct now, but may
need revision as the cards add algorithms. */
if(opt.personal_digest_prefs) if(opt.personal_digest_prefs)
{ {
prefitem_t *prefs; prefitem_t *prefs;
for(prefs=opt.personal_digest_prefs;prefs->type;prefs++) for(prefs=opt.personal_digest_prefs;prefs->type;prefs++)
if(md_digest_length(prefs->value)==20) if(prefs->value==DIGEST_ALGO_SHA1
|| prefs->value==DIGEST_ALGO_RMD160)
return prefs->value; return prefs->value;
} }
@ -822,22 +879,35 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
int hashlen=0,algo; int hashlen=0,algo;
/* Of course, if the recipient asks for something /* Of course, if the recipient asks for something
unreasonable (like a non-160-bit hash for DSA, for unreasonable (like a non-160-bit hash for DSA without
example), then don't do it. Check all sk's - if any --enable-dsa2, for example), then don't do it. Check
are DSA, then the hash must be 160-bit. In the future all sk's - if any are DSA, then the hash has
this can be more complex with different hashes for each restrictions. In the future this can be more complex
sk, but so long as there is only one signing algorithm with different hashes for each sk, but so long as there
with hash restrictions, this is ok. -dms */ 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 ) 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 if(sk_rover->sk->pubkey_algo==PUBKEY_ALGO_DSA)
&& sk_rover->sk->protect.s2k.mode==1002)) {
hashlen=20; if(opt.flags.dsa2)
hashlen=mpi_get_nbits(sk_rover->sk->skey[1])/8;
else
hashlen=20;
break;
}
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;
}
}
if((algo= if((algo=
select_algo_from_prefs(pk_list,PREFTYPE_HASH,-1, select_algo_from_prefs(pk_list,PREFTYPE_HASH,-1,
@ -1350,16 +1420,19 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
{ {
/* Basically, this means use SHA1 always unless it's a v3 RSA /* Basically, this means use SHA1 always unless it's a v3 RSA
key making a v3 cert (use MD5), or the user specified key making a v3 cert (use MD5), or the user specified
something (use whatever they said). They still must use a something (use whatever they said), or it's DSA (use the
160-bit hash with DSA, or the signature will fail. Note best match). They still can't pick an inappropriate hash
that this still allows the caller of make_keysig_packet to for DSA or the signature will fail. Note that this still
override the user setting if it must. */ allows the caller of make_keysig_packet to override the
user setting if it must. */
if(opt.cert_digest_algo) if(opt.cert_digest_algo)
digest_algo=opt.cert_digest_algo; digest_algo=opt.cert_digest_algo;
else if(sk->pubkey_algo==PUBKEY_ALGO_RSA else if(sk->pubkey_algo==PUBKEY_ALGO_RSA
&& pk->version<4 && sigversion<4) && pk->version<4 && sigversion<4)
digest_algo = DIGEST_ALGO_MD5; digest_algo = DIGEST_ALGO_MD5;
else if(sk->pubkey_algo==PUBKEY_ALGO_DSA)
digest_algo = match_dsa_hash(mpi_get_nbits(sk->skey[1])/8);
else else
digest_algo = DIGEST_ALGO_SHA1; digest_algo = DIGEST_ALGO_SHA1;
} }