From a92fa61c48c4b2673ecf04902723a6429384ec47 Mon Sep 17 00:00:00 2001 From: David Shaw Date: Wed, 28 Nov 2007 23:08:35 +0000 Subject: [PATCH] * sig-check.c (do_check): Code to try both the incorrect and correct SHA-224 DER prefixes when verifying a signature. See the change itself for more discussion. * main.h, seskey.c (do_encode_md): Rename to pkcs1_encode_md and make non-static. --- g10/ChangeLog | 11 +++++++++-- g10/main.h | 6 ++++-- g10/seskey.c | 18 ++++++++---------- g10/sig-check.c | 30 ++++++++++++++++++++++++++++-- 4 files changed, 49 insertions(+), 16 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 1c1d3de51..9f63972f9 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,5 +1,12 @@ 2007-11-28 David Shaw + * sig-check.c (do_check): Code to try both the incorrect and + correct SHA-224 DER prefixes when verifying a signature. See the + change itself for more discussion. + + * main.h, seskey.c (do_encode_md): Rename to pkcs1_encode_md and + make non-static. + * gpg.c (print_algo_names): New. (list_config): Use it here for the "ciphername" and "digestname" config items so we can get a script-parseable list of the names. @@ -13210,8 +13217,8 @@ Thu Feb 12 22:24:42 1998 Werner Koch (wk@frodo) * pubkey-enc.c (get_session_key): rewritten - Copyright 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, + 2007 Free Software Foundation, Inc. This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without diff --git a/g10/main.h b/g10/main.h index 63a2b04fd..1c48ca6cd 100644 --- a/g10/main.h +++ b/g10/main.h @@ -1,6 +1,6 @@ /* main.h - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - * 2006 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, + * 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -200,6 +200,8 @@ void try_make_homedir( const char *fname ); /*-- seskey.c --*/ void make_session_key( DEK *dek ); MPI encode_session_key( DEK *dek, unsigned nbits ); +MPI pkcs1_encode_md( MD_HANDLE md, int algo, size_t len, unsigned nbits, + const byte *asn, size_t asnlen ); MPI encode_md_value( PKT_public_key *pk, PKT_secret_key *sk, MD_HANDLE md, int hash_algo ); diff --git a/g10/seskey.c b/g10/seskey.c index 42e26fc4e..b47104d17 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -1,6 +1,6 @@ /* seskey.c - make sesssion keys etc. - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, - * 2006 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, + * 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -29,7 +29,6 @@ #include "main.h" #include "i18n.h" - /**************** * Make a session key and put it into DEK */ @@ -142,10 +141,9 @@ encode_session_key( DEK *dek, unsigned nbits ) return a; } - -static MPI -do_encode_md( MD_HANDLE md, int algo, size_t len, unsigned nbits, - const byte *asn, size_t asnlen ) +MPI +pkcs1_encode_md( MD_HANDLE md, int algo, size_t len, unsigned nbits, + const byte *asn, size_t asnlen ) { int nframe = (nbits+7) / 8; byte *frame; @@ -260,9 +258,9 @@ encode_md_value( PKT_public_key *pk, PKT_secret_key *sk, 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 ); + frame = pkcs1_encode_md( md, hash_algo, mdlen, + mpi_get_nbits(pk?pk->pkey[0]:sk->skey[0]), + asn, asnlen ); } return frame; diff --git a/g10/sig-check.c b/g10/sig-check.c index a01b7e083..bf8945e8b 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -1,6 +1,6 @@ /* sig-check.c - Check a signature - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, - * 2004 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, + * 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -280,6 +280,32 @@ do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest, rc = pubkey_verify( pk->pubkey_algo, result, sig->data, pk->pkey ); mpi_free( result ); + if(rc==G10ERR_BAD_SIGN && is_RSA(pk->pubkey_algo) + && sig->digest_algo==DIGEST_ALGO_SHA224) + { + /* This code is to work around a SHA-224 problem. RFC-4880 + and the drafts leading up to it were published with the + wrong DER prefix for SHA-224. Unfortunately, GPG pre-1.4.8 + used this wrong prefix. What this code does is take all + bad RSA signatures that use SHA-224, and re-checks them + using the old, incorrect, DER prefix. Someday we should + remove this code, and when we do remove it, pkcs1_encode_md + can be made into a static function again. Note that GPG2 + does not have this issue as it uses libgcrypt, which is + being fixed while it is still a development version. */ + + /* The incorrect SHA-224 DER prefix used in pre-1.4.8 */ + static byte asn[]={0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, + 0x00, 0x04, 0x20}; + + result=pkcs1_encode_md(digest,DIGEST_ALGO_SHA224,28, + mpi_get_nbits(pk->pkey[0]),asn,DIM(asn)); + + rc=pubkey_verify(pk->pubkey_algo,result,sig->data,pk->pkey); + mpi_free(result); + } + if( !rc && sig->flags.unknown_critical ) { log_info(_("assuming bad signature from key %s"