[svn] GnuPG - r4120 - trunk/g10
svn author dshaw
cvs at cvs.gnupg.org
Thu Apr 20 23:32:45 CEST 2006
Author: dshaw
Date: 2006-04-20 23:32:42 +0200 (Thu, 20 Apr 2006)
New Revision: 4120
Modified:
trunk/g10/ChangeLog
trunk/g10/gpg.c
trunk/g10/options.h
trunk/g10/pkclist.c
trunk/g10/sign.c
Log:
* 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.
Modified: trunk/g10/ChangeLog
===================================================================
--- trunk/g10/ChangeLog 2006-04-20 21:11:56 UTC (rev 4119)
+++ trunk/g10/ChangeLog 2006-04-20 21:32:42 UTC (rev 4120)
@@ -1,3 +1,21 @@
+2006-04-20 David Shaw <dshaw at 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 at jabberwocky.com>
* gpg.c (print_mds), armor.c (armor_filter, parse_hash_header):
Modified: trunk/g10/gpg.c
===================================================================
--- trunk/g10/gpg.c 2006-04-20 21:11:56 UTC (rev 4119)
+++ trunk/g10/gpg.c 2006-04-20 21:32:42 UTC (rev 4120)
@@ -362,6 +362,8 @@
oAutoKeyLocate,
oNoAutoKeyLocate,
oAllowMultisigVerification,
+ oEnableDSA2,
+ oDisableDSA2,
oNoop
};
@@ -699,6 +701,8 @@
{ oDebugCCIDDriver, "debug-ccid-driver", 0, "@"},
#endif
{ 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
product use gpg with minimal pain. Many commands are common
@@ -2659,6 +2663,9 @@
opt.allow_multisig_verification = 1;
break;
+ case oEnableDSA2: opt.flags.dsa2=1; break;
+ case oDisableDSA2: opt.flags.dsa2=0; break;
+
case oNoop: break;
default : pargs.err = configfp? 1:2; break;
Modified: trunk/g10/options.h
===================================================================
--- trunk/g10/options.h 2006-04-20 21:11:56 UTC (rev 4119)
+++ trunk/g10/options.h 2006-04-20 21:32:42 UTC (rev 4120)
@@ -222,6 +222,7 @@
unsigned int require_cross_cert:1;
unsigned int use_embedded_filename:1;
unsigned int utf8_filename:1;
+ unsigned int dsa2:1;
} flags;
/* Linked list of ways to find a key if the key isn't on the local
Modified: trunk/g10/pkclist.c
===================================================================
--- trunk/g10/pkclist.c 2006-04-20 21:11:56 UTC (rev 4119)
+++ trunk/g10/pkclist.c 2006-04-20 21:32:42 UTC (rev 4120)
@@ -1,6 +1,6 @@
/* pkclist.c
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
- * 2004, 2005 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+ * 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -1210,8 +1210,20 @@
}
else if( preftype == PREFTYPE_HASH )
{
- if(hint && ((*(int *)hint) != md_digest_length(algo)))
- return 0;
+ if(hint)
+ {
+ 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
&& algo != DIGEST_ALGO_SHA1
Modified: trunk/g10/sign.c
===================================================================
--- trunk/g10/sign.c 2006-04-20 21:11:56 UTC (rev 4119)
+++ trunk/g10/sign.c 2006-04-20 21:32:42 UTC (rev 4120)
@@ -319,10 +319,15 @@
}
else
{
- /* TODO: remove this check in the future once all the
- variable-q DSA stuff makes it into the standard. */
- if(!opt.expert
- && sk->pubkey_algo==PUBKEY_ALGO_DSA
+ /* 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"));
@@ -384,6 +389,29 @@
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
has a preferred algorithm (which is also filtered through
@@ -405,21 +433,50 @@
return opt.def_digest_algo;
else if( recipient_digest_algo )
return recipient_digest_algo;
- else if(sk->pubkey_algo==PUBKEY_ALGO_DSA
- || (sk->is_protected && sk->protect.s2k.mode==1002))
+ else if(sk->pubkey_algo==PUBKEY_ALGO_DSA)
{
- /* The sk lives on a smartcard, or it's a DSA key. DSA requires
- a 160-bit hash, and current smartcards only handle SHA-1 and
- RIPEMD/160 (i.e. 160-bit hashes). This is correct now, but
- may need revision as the cards add algorithms and/or DSA is
- expanded to use larger hashes. */
+ unsigned int qbytes=mpi_get_nbits(sk->skey[1])/8;
+ /* It's a DSA key, so find a hash that is the same size as q or
+ larger. If q is 160, assume it is an old DSA key and use a
+ 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)
+ {
+ prefitem_t *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;
}
@@ -822,23 +879,36 @@
int hashlen=0,algo;
/* 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 */
+ 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 */
- /* 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(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;
+ }
+ 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=
select_algo_from_prefs(pk_list,PREFTYPE_HASH,-1,
hashlen?&hashlen:NULL))>0)
@@ -1350,16 +1420,19 @@
{
/* Basically, this means use SHA1 always unless it's a v3 RSA
key making a v3 cert (use MD5), or the user specified
- something (use whatever they said). They still must use a
- 160-bit hash with DSA, or the signature will fail. Note
- that this still allows the caller of make_keysig_packet to
- override the user setting if it must. */
+ something (use whatever they said), or it's DSA (use the
+ best match). They still can't pick an inappropriate hash
+ for DSA or the signature will fail. Note that this still
+ allows the caller of make_keysig_packet to override the
+ user setting if it must. */
if(opt.cert_digest_algo)
digest_algo=opt.cert_digest_algo;
else if(sk->pubkey_algo==PUBKEY_ALGO_RSA
&& pk->version<4 && sigversion<4)
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
digest_algo = DIGEST_ALGO_SHA1;
}
More information about the Gnupg-commits
mailing list