[svn] GnuPG - r4084 - trunk/g10
svn author dshaw
cvs at cvs.gnupg.org
Thu Mar 30 21:21:01 CEST 2006
Author: dshaw
Date: 2006-03-30 21:20:59 +0200 (Thu, 30 Mar 2006)
New Revision: 4084
Modified:
trunk/g10/ChangeLog
trunk/g10/main.h
trunk/g10/seskey.c
trunk/g10/sig-check.c
trunk/g10/sign.c
Log:
* main.h, seskey.c (encode_md_value): Modify to allow a q size greater
than 160 bits as per DSA2. This will allow us to verify and issue DSA2
signatures for some backwards compatibility once we start generating DSA2
keys.
* sign.c (do_sign), sig-check.c (do_check): Change all callers.
* sign.c (do_sign): Enforce the 160-bit check for new signatures here
since encode_md_value can handle non-160-bit digests now. This will need
to come out once the standard for DSA2 is firmed up.
Modified: trunk/g10/ChangeLog
===================================================================
--- trunk/g10/ChangeLog 2006-03-30 14:19:08 UTC (rev 4083)
+++ trunk/g10/ChangeLog 2006-03-30 19:20:59 UTC (rev 4084)
@@ -1,3 +1,16 @@
+2006-03-30 David Shaw <dshaw at jabberwocky.com>
+
+ * main.h, seskey.c (encode_md_value): Modify to allow a q size
+ greater than 160 bits as per DSA2. This will allow us to verify
+ and issue DSA2 signatures for some backwards compatibility once we
+ start generating DSA2 keys.
+ * sign.c (do_sign), sig-check.c (do_check): Change all callers.
+
+ * sign.c (do_sign): Enforce the 160-bit check for new signatures
+ here since encode_md_value can handle non-160-bit digests now.
+ This will need to come out once the standard for DSA2 is firmed
+ up.
+
2006-03-22 David Shaw <dshaw at jabberwocky.com>
* getkey.c (parse_auto_key_locate): Silently strip out duplicates
Modified: trunk/g10/main.h
===================================================================
--- trunk/g10/main.h 2006-03-30 14:19:08 UTC (rev 4083)
+++ trunk/g10/main.h 2006-03-30 19:20:59 UTC (rev 4084)
@@ -203,8 +203,8 @@
/*-- seskey.c --*/
void make_session_key( DEK *dek );
MPI encode_session_key( DEK *dek, unsigned nbits );
-MPI encode_md_value( int pubkey_algo, MD_HANDLE md,
- int hash_algo, unsigned nbits );
+MPI encode_md_value( PKT_public_key *pk, PKT_secret_key *sk,
+ MD_HANDLE md, int hash_algo );
/*-- import.c --*/
int parse_import_options(char *str,unsigned int *options,int noisy);
Modified: trunk/g10/seskey.c
===================================================================
--- trunk/g10/seskey.c 2006-03-30 14:19:08 UTC (rev 4083)
+++ trunk/g10/seskey.c 2006-03-30 19:20:59 UTC (rev 4084)
@@ -195,36 +195,76 @@
/****************
* Encode a message digest into an MPI.
- * v3compathack is used to work around a bug in old GnuPG versions
- * which did put the algo identifier inseatd of the block type 1 into
- * the encoded value. Setting this flag forces the old behaviour.
+ * If it's for a DSA signature, make sure that the hash is large
+ * enough to fill up q. If the hash is too big, take the leftmost
+ * bits.
*/
MPI
-encode_md_value( int pubkey_algo, MD_HANDLE md,
- int hash_algo, unsigned nbits )
+encode_md_value( PKT_public_key *pk, PKT_secret_key *sk,
+ MD_HANDLE md, int hash_algo )
{
- int algo = hash_algo? hash_algo : md_get_algo(md);
- const byte *asn;
- size_t asnlen, mdlen;
- MPI frame;
+ MPI frame;
- if( pubkey_algo == PUBKEY_ALGO_DSA ) {
- mdlen = md_digest_length (hash_algo);
- if (mdlen != 20) {
- log_error (_("DSA requires the use of a 160 bit hash algorithm\n"));
- return NULL;
- }
+ assert(hash_algo);
+ assert(pk || sk);
- frame = md_is_secure(md)? mpi_alloc_secure((md_digest_length(hash_algo)
- +BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB )
- : mpi_alloc((md_digest_length(hash_algo)
- +BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB );
- mpi_set_buffer( frame, md_read(md, hash_algo),
- md_digest_length(hash_algo), 0 );
+ if((pk?pk->pubkey_algo:sk->pubkey_algo) == PUBKEY_ALGO_DSA)
+ {
+ /* It's a DSA signature, so find out the size of q. */
+
+ unsigned int qbytes=mpi_get_nbits(pk?pk->pkey[1]:sk->skey[1]);
+
+ /* Make sure it is a multiple of 8 bits. */
+
+ if(qbytes%8)
+ {
+ log_error(_("DSA requires the hash length to be a"
+ " multiple of 8 bits\n"));
+ return NULL;
+ }
+
+ /* Don't allow any q smaller than 160 bits. This might need a
+ revisit as the DSA2 design firms up, but for now, we don't
+ want someone to issue signatures from a key with a 16-bit q
+ or something like that, which would look correct but allow
+ trivial forgeries. Yes, I know this rules out using MD5 with
+ DSA. ;) */
+
+ if(qbytes<160)
+ {
+ log_error(_("DSA key %s uses an unsafe (%u bit) hash\n"),
+ pk?keystr_from_pk(pk):keystr_from_sk(sk),qbytes);
+ return NULL;
+ }
+
+ qbytes/=8;
+
+ /* Check if we're too short. Too long is safe as we'll
+ automatically left-truncate. */
+
+ if(md_digest_length(hash_algo) < qbytes)
+ {
+ log_error(_("DSA key %s requires a %u bit or larger hash\n"),
+ pk?keystr_from_pk(pk):keystr_from_sk(sk),qbytes*8);
+ return NULL;
+ }
+
+ frame = md_is_secure(md)? mpi_alloc_secure((qbytes+BYTES_PER_MPI_LIMB-1)
+ / BYTES_PER_MPI_LIMB )
+ : mpi_alloc((qbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB );
+
+ mpi_set_buffer( frame, md_read(md, hash_algo), qbytes, 0 );
}
- else {
- asn = md_asn_oid( algo, &asnlen, &mdlen );
- frame = do_encode_md( md, algo, mdlen, nbits, asn, asnlen );
+ else
+ {
+ const byte *asn;
+ size_t asnlen,mdlen;
+
+ asn = md_asn_oid( hash_algo, &asnlen, &mdlen );
+ frame = do_encode_md( md, hash_algo, mdlen,
+ mpi_get_nbits(pk?pk->pkey[0]:sk->skey[0]),
+ asn, asnlen );
}
- return frame;
+
+ return frame;
}
Modified: trunk/g10/sig-check.c
===================================================================
--- trunk/g10/sig-check.c 2006-03-30 14:19:08 UTC (rev 4083)
+++ trunk/g10/sig-check.c 2006-03-30 19:20:59 UTC (rev 4084)
@@ -274,8 +274,7 @@
}
md_final( digest );
- result = encode_md_value( pk->pubkey_algo, digest, sig->digest_algo,
- mpi_get_nbits(pk->pkey[0]) );
+ result = encode_md_value( pk, NULL, digest, sig->digest_algo );
if (!result)
return G10ERR_GENERAL;
ctx.sig = sig;
Modified: trunk/g10/sign.c
===================================================================
--- trunk/g10/sign.c 2006-03-30 14:19:08 UTC (rev 4083)
+++ trunk/g10/sign.c 2006-03-30 19:20:59 UTC (rev 4084)
@@ -319,8 +319,17 @@
}
else
{
- frame = encode_md_value( sk->pubkey_algo, md,
- digest_algo, mpi_get_nbits(sk->skey[0]) );
+ /* 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
+ && md_digest_length(digest_algo)!=20)
+ {
+ log_error(_("DSA requires the use of a 160 bit hash algorithm\n"));
+ return G10ERR_GENERAL;
+ }
+
+ frame = encode_md_value( NULL, sk, md, digest_algo );
if (!frame)
return G10ERR_GENERAL;
rc = pubkey_sign( sk->pubkey_algo, sig->data, frame, sk->skey );
@@ -336,9 +345,7 @@
if( get_pubkey( pk, sig->keyid ) )
rc = G10ERR_NO_PUBKEY;
else {
- frame = encode_md_value (pk->pubkey_algo, md,
- sig->digest_algo,
- mpi_get_nbits(pk->pkey[0]) );
+ frame = encode_md_value (pk, NULL, md, sig->digest_algo );
if (!frame)
rc = G10ERR_GENERAL;
else
More information about the Gnupg-commits
mailing list