From 2f64c3538a38e2718dfad6b0542797b0afc6c44f Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 5 Jun 2000 21:28:41 +0000 Subject: [PATCH] See ChangeLog: Mon Jun 5 23:41:54 CEST 2000 Werner Koch --- TODO | 2 ++ doc/FAQ | 7 ++++++- doc/gpg.sgml | 9 +++++++++ g10/ChangeLog | 7 +++++++ g10/g10.c | 3 +++ g10/main.h | 2 +- g10/options.h | 3 ++- g10/seskey.c | 15 +++++++++++---- g10/sig-check.c | 19 +++++++++++++++---- g10/sign.c | 2 +- 10 files changed, 57 insertions(+), 12 deletions(-) diff --git a/TODO b/TODO index 4f442a9d2..4ab7e4603 100644 --- a/TODO +++ b/TODO @@ -12,6 +12,8 @@ * Replace Valid/Invalid by Known/Unknown? + * Add an option to disable automatic key retrieve while verifing + signatures. Scheduled for 1.1 ----------------- diff --git a/doc/FAQ b/doc/FAQ index a7ca82cc7..bbfb27df3 100644 --- a/doc/FAQ +++ b/doc/FAQ @@ -398,11 +398,16 @@ revoke all the subkeys installed on that machine and install new subkeys. - Q: In the edit meu the trust values is not displayed correctly after + Q: In the edit menu the trust values is not displayed correctly after signing uids - why? A: This happens because the some informations are stored immediately in the trustdb, but the actual trust calculation can be done after the save command. This is a not easy to fix design bug which will be addressed in GnuPG 1.1 + Q: An Elgamal signature does not verify anymore since version 1.0.2 + A: Use the option --emulate-md-encode-bug. + + Q: Old versions of GnuPG can't verify ElGamal signatures + A: Update to GnuPG 1.0.2 diff --git a/doc/gpg.sgml b/doc/gpg.sgml index 3ff12a4c7..fc63bdcb5 100644 --- a/doc/gpg.sgml +++ b/doc/gpg.sgml @@ -1312,6 +1312,15 @@ This is not for normal use. Use the source to see for what it might be useful. This is not for normal use. Use the source to see for what it might be useful. + +--emulate-md-encode-bug + +GnuPG versions prior to 1.0.2 had a bug in the way a signature was encode. +This options enables a workaround by checking faulty signatures again with +the encoding used in old versions. This may only happen for ElGamal signatures +which are not widely used. + + diff --git a/g10/ChangeLog b/g10/ChangeLog index 51c3973d0..1989b8f29 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,10 @@ +Mon Jun 5 23:41:54 CEST 2000 Werner Koch + + * seskey.c (do_encode_md, encode_md_value): Add new arg v3compathack to work + around a bug in old versions. + * sig-check.c (do_check): use the aboved workaround when enabled. + * g10.c: New option --emulate-md-decode-bug + Mon Jun 5 12:37:43 CEST 2000 Werner Koch * build-packet.c (do_mdc): New. diff --git a/g10/g10.c b/g10/g10.c index cf2bfd64e..ea7f8aaea 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -187,6 +187,7 @@ enum cmd_and_opt_values { aNull = 0, oIgnoreTimeConflict, oNoRandomSeedFile, oEmu3DESS2KBug, /* will be removed in 1.1 */ + oEmuMDEncodeBug, aTest }; @@ -367,6 +368,7 @@ static ARGPARSE_OPTS opts[] = { { oIgnoreTimeConflict, "ignore-time-conflict", 0, "@" }, { oNoRandomSeedFile, "no-random-seed-file", 0, "@" }, { oEmu3DESS2KBug, "emulate-3des-s2k-bug", 0, "@"}, + { oEmuMDEncodeBug, "emulate-md-encode-bug", 0, "@"}, {0} }; @@ -843,6 +845,7 @@ main( int argc, char **argv ) break; case oEmuChecksumBug: opt.emulate_bugs |= EMUBUG_GPGCHKSUM; break; case oEmu3DESS2KBug: opt.emulate_bugs |= EMUBUG_3DESS2K; break; + case oEmuMDEncodeBug: opt.emulate_bugs |= EMUBUG_MDENCODE; break; case oCompressSigs: opt.compress_sigs = 1; break; case oRunAsShmCP: #ifndef USE_SHM_COPROCESSING diff --git a/g10/main.h b/g10/main.h index 9ec141ebc..54e68db18 100644 --- a/g10/main.h +++ b/g10/main.h @@ -109,7 +109,7 @@ void try_make_homedir( const char *fname ); 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 ); + int hash_algo, unsigned nbits, int v3compathack ); /*-- comment.c --*/ KBNODE make_comment_node( const char *s ); diff --git a/g10/options.h b/g10/options.h index f2090a2f0..f5657f70f 100644 --- a/g10/options.h +++ b/g10/options.h @@ -66,7 +66,7 @@ struct { int rfc1991; int rfc2440; int pgp2_workarounds; - unsigned emulate_bugs; /* bug emulation flags EMUBUG_xxxx */ + unsigned int emulate_bugs; /* bug emulation flags EMUBUG_xxxx */ int shm_coprocess; const char *set_filename; const char *comment_string; @@ -95,6 +95,7 @@ struct { #define EMUBUG_GPGCHKSUM 1 #define EMUBUG_3DESS2K 2 +#define EMUBUG_MDENCODE 4 #define DBG_PACKET_VALUE 1 /* debug packet reading/writing */ #define DBG_MPI_VALUE 2 /* debug mpi details */ diff --git a/g10/seskey.c b/g10/seskey.c index d0fe5f9bf..1ccead716 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -142,7 +142,7 @@ encode_session_key( DEK *dek, unsigned nbits ) static MPI do_encode_md( MD_HANDLE md, int algo, size_t len, unsigned nbits, - const byte *asn, size_t asnlen ) + const byte *asn, size_t asnlen, int v3compathack ) { int nframe = (nbits+7) / 8; byte *frame; @@ -162,7 +162,7 @@ do_encode_md( MD_HANDLE md, int algo, size_t len, unsigned nbits, frame = md_is_secure(md)? m_alloc_secure( nframe ) : m_alloc( nframe ); n = 0; frame[n++] = 0; - frame[n++] = algo; + frame[n++] = v3compathack? algo : 1; /* block type */ i = nframe - len - asnlen -3 ; assert( i > 1 ); memset( frame+n, 0xff, i ); n += i; @@ -179,8 +179,15 @@ do_encode_md( MD_HANDLE md, int algo, size_t len, unsigned nbits, } +/**************** + * 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 vare force the old behaviour. + */ MPI -encode_md_value( int pubkey_algo, MD_HANDLE md, int hash_algo, unsigned nbits ) +encode_md_value( int pubkey_algo, MD_HANDLE md, int hash_algo, + unsigned nbits, int v3compathack ) { int algo = hash_algo? hash_algo : md_get_algo(md); const byte *asn; @@ -197,7 +204,7 @@ encode_md_value( int pubkey_algo, MD_HANDLE md, int hash_algo, unsigned nbits ) } else { asn = md_asn_oid( algo, &asnlen, &mdlen ); - frame = do_encode_md( md, algo, mdlen, nbits, asn, asnlen ); + frame = do_encode_md( md, algo, mdlen, nbits, asn, asnlen, v3compathack); } return frame; } diff --git a/g10/sig-check.c b/g10/sig-check.c index 6c51cc89f..1a7e8664e 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -374,13 +374,24 @@ do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest, md_final( digest ); result = encode_md_value( pk->pubkey_algo, digest, sig->digest_algo, - mpi_get_nbits(pk->pkey[0])); - + mpi_get_nbits(pk->pkey[0]), (sig->version < 4) ); ctx.sig = sig; ctx.md = digest; rc = pubkey_verify( pk->pubkey_algo, result, sig->data, pk->pkey, cmp_help, &ctx ); mpi_free( result ); + if( (opt.emulate_bugs & EMUBUG_MDENCODE) + && rc == G10ERR_BAD_SIGN && is_ELGAMAL(pk->pubkey_algo) ) { + /* In this case we try again because old GnuPG versions didn't encode + * the hash right. There is no problem with DSA here */ + result = encode_md_value( pk->pubkey_algo, digest, sig->digest_algo, + mpi_get_nbits(pk->pkey[0]), (sig->version < 4) ); + ctx.sig = sig; + ctx.md = digest; + rc = pubkey_verify( pk->pubkey_algo, result, sig->data, pk->pkey, + cmp_help, &ctx ); + } + if( !rc && sig->flags.unknown_critical ) { log_info(_("assuming bad signature due to an unknown critical bit\n")); rc = G10ERR_BAD_SIGN; @@ -518,7 +529,6 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig, keyid_from_pk( pk, keyid ); md = md_open( algo, 0 ); - md_start_debug( md, "rsa" ); hash_public_key( md, pk ); hash_uid_node( unode, md, sig ); if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) { @@ -526,8 +536,9 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig, *is_selfsig = 1; rc = do_check( pk, sig, md, r_expired ); } - else + else { rc = do_signature_check( sig, md, r_expiredate, r_expired ); + } md_close(md); } else { diff --git a/g10/sign.c b/g10/sign.c index e4b1b8f4e..6b6d5c5d0 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -128,7 +128,7 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig, sig->digest_start[0] = dp[0]; sig->digest_start[1] = dp[1]; frame = encode_md_value( sk->pubkey_algo, md, - digest_algo, mpi_get_nbits(sk->skey[0])); + digest_algo, mpi_get_nbits(sk->skey[0]), 0 ); rc = pubkey_sign( sk->pubkey_algo, sig->data, frame, sk->skey ); mpi_free(frame); if( rc )