diff options
40 files changed, 351 insertions, 455 deletions
@@ -1,3 +1,13 @@ +Noteworthy changes in version 0.3.0 +----------------------------------- + * New option --emulate-checksum-bug. If your passphrase does not + work anymore, use this option and --change-passphrase to rewrite + your passphrase. + + + + + Noteworthy changes in version 0.2.19 ------------------------------------ @@ -1 +1 @@ -0.2.19a +0.2.19b diff --git a/cipher/ChangeLog b/cipher/ChangeLog index 760f52d40..354206462 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,3 +1,7 @@ +Mon Jun 15 14:40:48 1998 Werner Koch (wk@isil.d.shuttle.de) + + * tiger.c: Removed from dis, will reappear as dynload module + Sat Jun 13 14:16:57 1998 Werner Koch (wk@isil.d.shuttle.de) * pubkey.c: Major changes to allow extensions. Changed the inteface diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 04d1ef8ed..2cb4ddc41 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -2,6 +2,7 @@ INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl -I../intl +EXTRA_DIST = tiger.c noinst_LIBRARIES = libcipher.a @@ -15,7 +16,6 @@ libcipher_a_SOURCES = cipher.c \ blowfish.h \ cast5.c \ cast5.h \ - des.h \ elgamal.c \ elgamal.h \ md5.c \ @@ -29,8 +29,6 @@ libcipher_a_SOURCES = cipher.c \ rand-dummy.c \ rmd.h \ rmd160.c \ - tiger.h \ - tiger.c \ sha1.h \ sha1.c \ dsa.h \ diff --git a/cipher/cipher.c b/cipher/cipher.c index 064947865..cedcb37af 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -31,7 +31,6 @@ #include "cipher.h" #include "blowfish.h" #include "cast5.h" -#include "des.h" #include "dynload.h" @@ -64,7 +63,6 @@ struct cipher_handle_s { }; - static void dummy_setkey( void *c, byte *key, unsigned keylen ) { } static void diff --git a/cipher/des.c b/cipher/des.c index 53afbc3ca..3864b2214 100644 --- a/cipher/des.c +++ b/cipher/des.c @@ -25,7 +25,13 @@ #include <assert.h> #include "util.h" #include "types.h" -#include "des.h" + +#define DES_BLOCKSIZE 8 +#define DES_ROUNDS 16 + +typedef struct { + int tripledes; +} DES_context; static const int IP[64] = { diff --git a/cipher/des.h b/cipher/des.h deleted file mode 100644 index 55a927703..000000000 --- a/cipher/des.h +++ /dev/null @@ -1,37 +0,0 @@ -/* des.h - * Copyright (C) 1998 Free Software Foundation, Inc. - * - * This file is part of GNUPG. - * - * GNUPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GNUPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ -#ifndef G10_DES_H -#define G10_DES_H - -#include "types.h" - -#define DES_BLOCKSIZE 8 -#define DES_ROUNDS 16 - -typedef struct { - int tripledes; -} DES_context; - -void des_setkey( DES_context *c, byte *key, unsigned keylen ); -void des_3des_setkey( DES_context *c, byte *key, unsigned keylen ); -void des_encrypt_block( DES_context *bc, byte *outbuf, byte *inbuf ); -void des_decrypt_block( DES_context *bc, byte *outbuf, byte *inbuf ); - -#endif /*G10_DES_H*/ diff --git a/cipher/dsa.c b/cipher/dsa.c index 20011da38..19a59d909 100644 --- a/cipher/dsa.c +++ b/cipher/dsa.c @@ -359,7 +359,8 @@ dsa_sign( int algo, MPI *resarr, MPI data, MPI *skey ) } int -dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey ) +dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey, + int (*cmp)(void *, MPI), void *opaquev ) { DSA_public_key pk; diff --git a/cipher/dsa.h b/cipher/dsa.h index fe977a645..dda32bd6d 100644 --- a/cipher/dsa.h +++ b/cipher/dsa.h @@ -23,7 +23,8 @@ int dsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ); int dsa_check_secret_key( int algo, MPI *skey ); int dsa_sign( int algo, MPI *resarr, MPI data, MPI *skey ); -int dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey ); +int dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey, + int (*cmp)(void *, MPI), void *opaquev ); unsigned dsa_get_nbits( int algo, MPI *pkey ); const char *dsa_get_info( int algo, int *npkey, int *nskey, int *nenc, int *nsig, int *usage ); diff --git a/cipher/dynload.c b/cipher/dynload.c index e0b2e77e3..71f0d1959 100644 --- a/cipher/dynload.c +++ b/cipher/dynload.c @@ -221,7 +221,8 @@ enum_gnupgext_pubkeys( void **enum_context, int *algo, int (**encrypt)( int algo, MPI *resarr, MPI data, MPI *pkey ), int (**decrypt)( int algo, MPI *result, MPI *data, MPI *skey ), int (**sign)( int algo, MPI *resarr, MPI data, MPI *skey ), - int (**verify)( int algo, MPI hash, MPI *data, MPI *pkey ), + int (**verify)( int algo, MPI hash, MPI *data, MPI *pkey, + int (*cmp)(void *, MPI), void *opaquev ), unsigned (**get_nbits)( int algo, MPI *pkey ) ) { EXTLIST r; @@ -232,7 +233,8 @@ enum_gnupgext_pubkeys( void **enum_context, int *algo, int (**)( int, MPI *, MPI , MPI * ), int (**)( int, MPI *, MPI *, MPI * ), int (**)( int, MPI *, MPI , MPI * ), - int (**)( int, MPI , MPI *, MPI * ), + int (**)( int, MPI , MPI *, MPI *, + int (*)(void*,MPI), void *), unsigned (**)( int , MPI * ) ); if( !*enum_context ) { /* init context */ diff --git a/cipher/dynload.h b/cipher/dynload.h index 69b5d8fa9..2d829c717 100644 --- a/cipher/dynload.h +++ b/cipher/dynload.h @@ -36,7 +36,8 @@ enum_gnupgext_pubkeys( void **enum_context, int *algo, int (**encrypt)( int algo, MPI *resarr, MPI data, MPI *pkey ), int (**decrypt)( int algo, MPI *result, MPI *data, MPI *skey ), int (**sign)( int algo, MPI *resarr, MPI data, MPI *skey ), - int (**verify)( int algo, MPI hash, MPI *data, MPI *pkey ), + int (**verify)( int algo, MPI hash, MPI *data, MPI *pkey, + int (*cmp)(void *, MPI), void *opaquev ), unsigned (**get_nbits)( int algo, MPI *pkey ) ); #endif /*G10_CIPHER_DYNLOAD_H*/ diff --git a/cipher/elgamal.c b/cipher/elgamal.c index b37c756cf..bcaaa20ba 100644 --- a/cipher/elgamal.c +++ b/cipher/elgamal.c @@ -476,7 +476,8 @@ elg_sign( int algo, MPI *resarr, MPI data, MPI *skey ) } int -elg_verify( int algo, MPI hash, MPI *data, MPI *pkey ) +elg_verify( int algo, MPI hash, MPI *data, MPI *pkey, + int (*cmp)(void *, MPI), void *opaquev ) { ELG_public_key pk; diff --git a/cipher/elgamal.h b/cipher/elgamal.h index a4668ff9d..672f07704 100644 --- a/cipher/elgamal.h +++ b/cipher/elgamal.h @@ -25,7 +25,8 @@ int elg_check_secret_key( int algo, MPI *skey ); int elg_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ); int elg_decrypt( int algo, MPI *result, MPI *data, MPI *skey ); int elg_sign( int algo, MPI *resarr, MPI data, MPI *skey ); -int elg_verify( int algo, MPI hash, MPI *data, MPI *pkey ); +int elg_verify( int algo, MPI hash, MPI *data, MPI *pkey, + int (*cmp)(void *, MPI), void *opaquev ); unsigned elg_get_nbits( int algo, MPI *pkey ); const char *elg_get_info( int algo, int *npkey, int *nskey, int *nenc, int *nsig, int *usage ); diff --git a/cipher/g10c.c b/cipher/g10c.c index c6f94022b..5bf0eb61f 100644 --- a/cipher/g10c.c +++ b/cipher/g10c.c @@ -27,6 +27,7 @@ #define _g10lib_INTERNAL 1 #include "g10lib.h" +const char *g10c_revision_string(int dummy) { return "$Revision$"; } MPI g10c_generate_secret_prime( unsigned nbits ) diff --git a/cipher/md.c b/cipher/md.c index 30d7e255d..b116dd975 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -38,7 +38,6 @@ static struct { const char *name; int algo;} digest_names[] = { { "RMD160", DIGEST_ALGO_RMD160 }, { "RMD-160", DIGEST_ALGO_RMD160 }, { "RIPE-MD-160", DIGEST_ALGO_RMD160 }, - { "TIGER", DIGEST_ALGO_TIGER }, {NULL} }; @@ -79,9 +78,6 @@ int check_digest_algo( int algo ) { switch( algo ) { - #ifdef WITH_TIGER_HASH - case DIGEST_ALGO_TIGER: - #endif case DIGEST_ALGO_MD5: case DIGEST_ALGO_RMD160: case DIGEST_ALGO_SHA1: @@ -134,13 +130,6 @@ md_enable( MD_HANDLE h, int algo ) sha1_init( &h->sha1 ); h->use_sha1 = 1; } - #ifdef WITH_TIGER_HASH - else if( algo == DIGEST_ALGO_TIGER ) { - if( !h->use_tiger ) - tiger_init( &h->tiger ); - h->use_tiger = 1; - } - #endif else log_bug("md_enable(%d)", algo ); } @@ -186,12 +175,6 @@ md_write( MD_HANDLE a, byte *inbuf, size_t inlen) sha1_write( &a->sha1, a->buffer, a->bufcount ); sha1_write( &a->sha1, inbuf, inlen ); } - #ifdef WITH_TIGER_HASH - if( a->use_tiger ) { - tiger_write( &a->tiger, a->buffer, a->bufcount ); - tiger_write( &a->tiger, inbuf, inlen ); - } - #endif if( a->use_md5 ) { md5_write( &a->md5, a->buffer, a->bufcount ); md5_write( &a->md5, inbuf, inlen ); @@ -210,10 +193,6 @@ md_final(MD_HANDLE a) rmd160_final( &a->rmd160 ); if( a->use_sha1 ) sha1_final( &a->sha1 ); - #ifdef WITH_TIGER_HASH - if( a->use_tiger ) - tiger_final( &a->tiger ); - #endif if( a->use_md5 ) md5_final( &a->md5 ); } @@ -230,10 +209,6 @@ md_read( MD_HANDLE a, int algo ) return rmd160_read( &a->rmd160 ); if( a->use_sha1 ) return sha1_read( &a->sha1 ); - #ifdef WITH_TIGER_HASH - if( a->use_tiger ) - return tiger_read( &a->tiger ); - #endif if( a->use_md5 ) return md5_read( &a->md5 ); } @@ -242,10 +217,6 @@ md_read( MD_HANDLE a, int algo ) return rmd160_read( &a->rmd160 ); if( algo == DIGEST_ALGO_SHA1 ) return sha1_read( &a->sha1 ); - #ifdef WITH_TIGER_HASH - if( algo == DIGEST_ALGO_TIGER ) - return tiger_read( &a->tiger ); - #endif if( algo == DIGEST_ALGO_MD5 ) return md5_read( &a->md5 ); } @@ -259,10 +230,6 @@ md_get_algo( MD_HANDLE a ) return DIGEST_ALGO_RMD160; if( a->use_sha1 ) return DIGEST_ALGO_SHA1; - #ifdef WITH_TIGER_HASH - if( a->use_tiger ) - return DIGEST_ALGO_TIGER; - #endif if( a->use_md5 ) return DIGEST_ALGO_MD5; return 0; @@ -275,8 +242,6 @@ int md_digest_length( int algo ) { switch( algo ) { - case DIGEST_ALGO_TIGER: - return 24; case DIGEST_ALGO_RMD160: case DIGEST_ALGO_SHA1: return 20; diff --git a/cipher/md.h b/cipher/md.h index 2d45a1273..b4d690793 100644 --- a/cipher/md.h +++ b/cipher/md.h @@ -25,7 +25,6 @@ #include "rmd.h" #include "sha1.h" #include "md5.h" -#include "tiger.h" #define MD_BUFFER_SIZE 512 diff --git a/cipher/pubkey.c b/cipher/pubkey.c index 3357ae12c..b18f1c316 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -28,6 +28,8 @@ #include "errors.h" #include "mpi.h" #include "cipher.h" +#include "elgamal.h" +#include "dsa.h" #include "dynload.h" @@ -46,7 +48,8 @@ struct pubkey_table_s { int (*encrypt)( int algo, MPI *resarr, MPI data, MPI *pkey ); int (*decrypt)( int algo, MPI *result, MPI *data, MPI *skey ); int (*sign)( int algo, MPI *resarr, MPI data, MPI *skey ); - int (*verify)( int algo, MPI hash, MPI *data, MPI *pkey ); + int (*verify)( int algo, MPI hash, MPI *data, MPI *pkey, + int (*cmp)(void *, MPI), void *opaquev ); unsigned (*get_nbits)( int algo, MPI *pkey ); }; @@ -75,7 +78,8 @@ dummy_sign( int algo, MPI *resarr, MPI data, MPI *skey ) { log_bug("no sign() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } static int -dummy_verify( int algo, MPI hash, MPI *data, MPI *pkey ) +dummy_verify( int algo, MPI hash, MPI *data, MPI *pkey, + int (*cmp)(void *, MPI), void *opaquev ) { log_bug("no verify() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } static unsigned @@ -523,7 +527,8 @@ pubkey_sign( int algo, MPI *resarr, MPI data, MPI *skey ) * Return 0 if the signature is good */ int -pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey ) +pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey, + int (*cmp)(void *, MPI), void *opaquev ) { int i, rc; @@ -531,7 +536,8 @@ pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey ) do { for(i=0; pubkey_table[i].name; i++ ) if( pubkey_table[i].algo == algo ) { - rc = (*pubkey_table[i].verify)( algo, hash, data, pkey ); + rc = (*pubkey_table[i].verify)( algo, hash, data, pkey, + cmp, opaquev ); goto ready; } } while( load_pubkey_modules() ); diff --git a/cipher/tiger.c b/cipher/tiger.c index c43226445..11c11b461 100644 --- a/cipher/tiger.c +++ b/cipher/tiger.c @@ -25,9 +25,15 @@ #include <assert.h> #include "util.h" #include "memory.h" -#include "tiger.h" -#ifdef WITH_TIGER_HASH + +typedef struct { + u64 a, b, c; + u32 nblocks; + byte buf[64]; + int count; +} TIGER_CONTEXT; + /********************************* * Okay, okay, this is not the fastest code - improvements are welcome. @@ -845,5 +851,3 @@ tiger_final( TIGER_CONTEXT *hd ) #undef X } -#endif /* WITH_TIGER_HASH */ - diff --git a/cipher/tiger.h b/cipher/tiger.h deleted file mode 100644 index 906909269..000000000 --- a/cipher/tiger.h +++ /dev/null @@ -1,44 +0,0 @@ -/* tiger.h - TIGER hash function - * Copyright (C) 1998 Free Software Foundation, Inc. - * - * This file is part of GNUPG. - * - * GNUPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GNUPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ -#ifndef G10_TIGER_H -#define G10_TIGER_H - -#include "types.h" - -#ifdef HAVE_U64_TYPEDEF - -#define WITH_TIGER_HASH 1 - -typedef struct { - u64 a, b, c; - u32 nblocks; - byte buf[64]; - int count; -} TIGER_CONTEXT; - - -void tiger_init( TIGER_CONTEXT *c ); -void tiger_write( TIGER_CONTEXT *hd, byte *inbuf, size_t inlen); -void tiger_final(TIGER_CONTEXT *hd); -#define tiger_read(h) ( (h)->buf ) - -#endif /* HAVE_TIGER_HASH */ - -#endif /*G10_TIGER_H*/ diff --git a/g10/ChangeLog b/g10/ChangeLog index d6ed0cc6d..15fd2c81b 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,6 +1,13 @@ +Sun Jun 14 21:28:31 1998 Werner Koch (wk@isil.d.shuttle.de) + + * misc.c (checksum_u16): Fixed a stupid bug which caused a + wrong checksum calculation for the secret key protection and + add a backward compatibility option. + * g10.c (main): Add option --emulate-checksum-bug. + Thu Jun 11 13:26:44 1998 Werner Koch (wk@isil.d.shuttle.de) - * packet.h: Mjor chnages to the structure of public key material + * packet.h: Major changes to the structure of public key material which is now stored in an array and not anaymore in a union of algorithm specific structures. These is needed to make the system more extendable and makes a lot of stuff much simpler. Changed @@ -164,6 +164,7 @@ static ARGPARSE_OPTS opts[] = { { 553, "skip-verify",0, "@" }, { 557, "compress-keys",0, "@"}, { 559, "always-trust", 0, "@"}, + { 562, "emulate-checksum-bug", 0, "@"}, {0} }; @@ -310,11 +311,6 @@ wrong_args( const char *text) static void set_debug(void) { - volatile char *p = g10_malloc(1); - volatile MPI a = g10m_new(1); - *p = g10c_get_random_byte( 0 ); - - if( opt.debug & DBG_MEMORY_VALUE ) memory_debug_mode = 1; if( opt.debug & DBG_MEMSTAT_VALUE ) @@ -598,6 +594,7 @@ main( int argc, char **argv ) case 559: opt.always_trust = 1; break; case 560: register_cipher_extension(pargs.r.ret_str); break; case 561: opt.rfc1991 = 1; break; + case 562: opt.emulate_bugs |= 1; break; default : errors++; pargs.err = configfp? 1:2; break; } } @@ -1111,9 +1108,8 @@ print_mds( const char *fname, int algo ) md_enable( md, DIGEST_ALGO_MD5 ); md_enable( md, DIGEST_ALGO_SHA1 ); md_enable( md, DIGEST_ALGO_RMD160 ); - #ifdef WITH_TIGER_HASH - md_enable( md, DIGEST_ALGO_TIGER ); - #endif + if( !check_digest_algo(DIGEST_ALGO_TIGER) ) + md_enable( md, DIGEST_ALGO_TIGER ); } while( (n=fread( buf, 1, DIM(buf), fp )) ) @@ -1134,10 +1130,10 @@ print_mds( const char *fname, int algo ) print_hex(md_read(md, DIGEST_ALGO_SHA1), 20 ); printf("\n%sRMD160 = ", fname?pname:"" ); print_hex(md_read(md, DIGEST_ALGO_RMD160), 20 ); - #ifdef WITH_TIGER_HASH - printf("\n%s TIGER = ", fname?pname:"" ); + if( !check_digest_algo(DIGEST_ALGO_TIGER) ) { + printf("\n%s TIGER = ", fname?pname:"" ); print_hex(md_read(md, DIGEST_ALGO_TIGER), 24 ); - #endif + } } putchar('\n'); } diff --git a/g10/gpgd.c b/g10/gpgd.c index 72fcade8d..34158b7f9 100644 --- a/g10/gpgd.c +++ b/g10/gpgd.c @@ -129,7 +129,7 @@ set_debug(void) if( opt.debug & DBG_MPI_VALUE ) mpi_debug_mode = 1; if( opt.debug & DBG_CIPHER_VALUE ) - cipher_debug_mode = 1; + g10c_debug_mode = 1; if( opt.debug & DBG_IOBUF_VALUE ) iobuf_debug_mode = 1; } diff --git a/g10/keygen.c b/g10/keygen.c index 8ad30bb9b..21c388bfc 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -168,7 +168,7 @@ gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, skc->is_protected = 0; skc->protect.algo = 0; - skc->csum = checksum_mpi( skc->skey[3] ); + skc->csum = checksum_mpi_counted_nbits( skc->skey[3] ); if( ret_skc ) /* not a subkey: return an unprotected version of the skc */ *ret_skc = copy_secret_cert( NULL, skc ); @@ -232,10 +232,10 @@ gen_rsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, skc->d.rsa.rsa_p = sk.p; skc->d.rsa.rsa_q = sk.q; skc->d.rsa.rsa_u = sk.u; - skc->d.rsa.csum = checksum_mpi( skc->d.rsa.rsa_d ); - skc->d.rsa.csum += checksum_mpi( skc->d.rsa.rsa_p ); - skc->d.rsa.csum += checksum_mpi( skc->d.rsa.rsa_q ); - skc->d.rsa.csum += checksum_mpi( skc->d.rsa.rsa_u ); + skc->d.rsa.csum = checksum_mpi_counted_nbits( skc->d.rsa.rsa_d ); + skc->d.rsa.csum += checksum_mpi_counted_nbits( skc->d.rsa.rsa_p ); + skc->d.rsa.csum += checksum_mpi_counted_nbits( skc->d.rsa.rsa_q ); + skc->d.rsa.csum += checksum_mpi_counted_nbits( skc->d.rsa.rsa_u ); if( ret_skc ) /* not a subkey: return an unprotected version of the skc */ *ret_skc = copy_secret_cert( NULL, skc ); @@ -244,7 +244,8 @@ gen_rsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, skc->d.rsa.is_protected = 1; skc->d.rsa.protect_algo = CIPHER_ALGO_BLOWFISH; randomize_buffer( skc->d.rsa.protect.blowfish.iv, 8, 1); - skc->d.rsa.csum += checksum( skc->d.rsa.protect.blowfish.iv, 8 ); + skc->d.rsa.csum += checksum_counted_nbits( + skc->d.rsa.protect.blowfish.iv, 8 ); rc = protect_secret_key( skc, dek ); if( rc ) { log_error("protect_secret_key failed: %s\n", g10_errstr(rc) ); @@ -314,7 +315,7 @@ gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, skc->is_protected = 0; skc->protect.algo = 0; - skc->csum = checksum_mpi( skc->skey[4] ); + skc->csum = checksum_mpi_counted_nbits( skc->skey[4] ); if( ret_skc ) /* not a subkey: return an unprotected version of the skc */ *ret_skc = copy_secret_cert( NULL, skc ); diff --git a/g10/main.h b/g10/main.h index 56fd3c9d5..0b30084e3 100644 --- a/g10/main.h +++ b/g10/main.h @@ -49,6 +49,7 @@ void trap_unaligned(void); u16 checksum_u16( unsigned n ); u16 checksum( byte *p, unsigned n ); u16 checksum_mpi( MPI a ); +u16 checksum_mpi_counted_nbits( MPI a ); /*-- encode.c --*/ int encode_symmetric( const char *filename ); @@ -85,7 +86,8 @@ IOBUF open_sigfile( const char *iname ); /*-- seskey.c --*/ void make_session_key( DEK *dek ); MPI encode_session_key( DEK *dek, unsigned nbits ); -MPI encode_md_value( MD_HANDLE md, int hash_algo, unsigned nbits ); +MPI encode_md_value( int pubkey_algo, MD_HANDLE md, + int hash_algo, unsigned nbits ); /*-- comment.c --*/ KBNODE make_comment_node( const char *s ); diff --git a/g10/mainproc.c b/g10/mainproc.c index 707272be0..a807f85d9 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -246,7 +246,8 @@ proc_plaintext( CTX c, PACKET *pkt ) /*md_start_debug(c->mfx.md, "proc_plaintext");*/ md_enable( c->mfx.md, DIGEST_ALGO_SHA1 ); md_enable( c->mfx.md, DIGEST_ALGO_MD5 ); - md_enable( c->mfx.md, DIGEST_ALGO_TIGER ); + if( !check_digest_algo(DIGEST_ALGO_TIGER) ) + md_enable( c->mfx.md, DIGEST_ALGO_TIGER ); rc = handle_plaintext( pt, &c->mfx ); if( rc ) log_error( "handle plaintext failed: %s\n", g10_errstr(rc)); diff --git a/g10/misc.c b/g10/misc.c index 782b5cd10..d1bacf694 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -28,7 +28,15 @@ #endif #include "util.h" #include "main.h" +#include "options.h" +volatile int +pull_in_libs(void) +{ + g10m_revision_string(0); + g10c_revision_string(0); + g10u_revision_string(0); +} #if defined(__linux__) && defined(__alpha__) @@ -63,7 +71,22 @@ checksum_u16( unsigned n ) u16 a; a = (n >> 8) & 0xff; - a |= n & 0xff; + if( opt.emulate_bugs & 1 ) { + a |= n & 0xff; + log_debug("csum_u16 emulated for n=%u\n", n); + } + else + a += n & 0xff; + return a; +} + +static u16 +checksum_u16_nobug( unsigned n ) +{ + u16 a; + + a = (n >> 8) & 0xff; + a += n & 0xff; return a; } @@ -83,12 +106,43 @@ checksum_mpi( MPI a ) u16 csum; byte *buffer; unsigned nbytes; + unsigned nbits; buffer = mpi_get_buffer( a, &nbytes, NULL ); - csum = checksum_u16( mpi_get_nbits(a) ); + /* some versions of gpg encode wrong values for the length of an mpi + * so that mpi_get_nbits() which counts the mpi yields another (shorter) + * value than the one store with the mpi. mpi_get_nbit_info() returns + * this stored value if it is still available. + */ + + if( opt.emulate_bugs & 1 ) + nbits = 0; + else + nbits = mpi_get_nbit_info(a); + if( !nbits ) + nbits = mpi_get_nbits(a); + csum = checksum_u16( nbits ); csum += checksum( buffer, nbytes ); m_free( buffer ); return csum; } +/**************** + * This is the correct function + */ +u16 +checksum_mpi_counted_nbits( MPI a ) +{ + u16 csum; + byte *buffer; + unsigned nbytes; + unsigned nbits; + + buffer = mpi_get_buffer( a, &nbytes, NULL ); + nbits = mpi_get_nbits(a); + csum = checksum_u16_nobug( nbits ); + csum += checksum( buffer, nbytes ); + m_free( buffer ); + return csum; +} diff --git a/g10/options.h b/g10/options.h index 4b32b524c..1e34ced08 100644 --- a/g10/options.h +++ b/g10/options.h @@ -48,6 +48,7 @@ struct { int compress_keys; int always_trust; int rfc1991; + unsigned emulate_bugs; /* bug emulation flags */ } opt; diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 0cd4238ad..9e469b644 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -64,6 +64,7 @@ static int parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, static int parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ); + static unsigned short read_16(IOBUF inp) { @@ -1006,9 +1007,6 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen, cert->csum = read_16(inp); pktlen -= 2; if( list_mode ) { - printf("\telg x: "); - mpi_print(stdout, cert->skey[3], mpi_print_mode ); - putchar('\n'); printf("\t[secret value x is not shown]\n" "\tchecksum: %04hx\n", cert->csum); } @@ -1174,8 +1172,7 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen, printf(" %02x", temp[i] ); putchar('\n'); } - if( cert->protect.algo == CIPHER_ALGO_BLOWFISH160 ) - memcpy(cert->protect.iv, temp, 8 ); + memcpy(cert->protect.iv, temp, 8 ); /* old version, we don't have a S2K, so we fake one */ cert->protect.s2k.mode = 0; cert->protect.s2k.hash_algo = DIGEST_ALGO_MD5; diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index 9ac19c89c..f30e5d0e9 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -39,7 +39,7 @@ do_check( PKT_secret_cert *cert ) { byte *buffer; u16 csum=0; - int res; + int i, res; unsigned nbytes; if( cert->is_protected ) { /* remove the protection */ @@ -60,60 +60,34 @@ do_check( PKT_secret_cert *cert ) CIPHER_MODE_AUTO_CFB, 1); cipher_setkey( cipher_hd, dek->key, dek->keylen ); cipher_setiv( cipher_hd, NULL ); - m_free(dek); /* pw is in secure memory, so m_free() burns it */ + m_free(dek); save_cert = copy_secret_cert( NULL, cert ); memcpy(save_iv, cert->protect.iv, 8 ); cipher_decrypt( cipher_hd, cert->protect.iv, cert->protect.iv, 8 ); - switch( cert->pubkey_algo ) { - case PUBKEY_ALGO_ELGAMAL: - case PUBKEY_ALGO_ELGAMAL_E: - /* FIXME: removed ELG knowledge from this function */ - buffer = mpi_get_secure_buffer( cert->skey[3], &nbytes, NULL ); + csum = 0; + for(i=pubkey_get_npkey(cert->pubkey_algo); + i < pubkey_get_nskey(cert->pubkey_algo); i++ ) { + buffer = mpi_get_secure_buffer( cert->skey[i], &nbytes, NULL ); + cipher_sync( cipher_hd ); cipher_decrypt( cipher_hd, buffer, buffer, nbytes ); - mpi_set_buffer( cert->skey[3], buffer, nbytes, 0 ); - csum = checksum_mpi( cert->skey[3] ); + mpi_set_buffer( cert->skey[i], buffer, nbytes, 0 ); + csum += checksum_mpi( cert->skey[i] ); m_free( buffer ); - break; - case PUBKEY_ALGO_DSA: - buffer = mpi_get_secure_buffer( cert->skey[4], &nbytes, NULL ); - cipher_decrypt( cipher_hd, buffer, buffer, nbytes ); - mpi_set_buffer( cert->skey[4], buffer, nbytes, 0 ); - csum = checksum_mpi( cert->skey[4] ); - m_free( buffer ); - break; - case PUBKEY_ALGO_RSA: - case PUBKEY_ALGO_RSA_E: - case PUBKEY_ALGO_RSA_S: - csum = 0; - #define X(a) do { \ - buffer = mpi_get_secure_buffer( cert->skey[(a)], \ - &nbytes, NULL ); \ - csum += checksum_u16( nbytes*8 ); \ - cipher_decrypt( cipher_hd, buffer, buffer, nbytes ); \ - csum += checksum( buffer, nbytes ); \ - mpi_set_buffer(cert->skey[(a)], buffer, nbytes, 0 ); \ - m_free( buffer ); \ - } while(0) - X(2); - X(3); - X(4); - X(5); - #undef X - break; - - default: BUG(); + } + if( opt.emulate_bugs & 1 ) { + log_debug("secret key csum is=%04hx should=%04hx algos=%d/%d\n", + csum, cert->csum, cert->pubkey_algo,cert->protect.algo ); + csum = cert->csum; } cipher_close( cipher_hd ); /* now let's see whether we have used the right passphrase */ if( csum != cert->csum ) { - if( csum != cert->csum ) { - copy_secret_cert( cert, save_cert ); - free_secret_cert( save_cert ); - memcpy( cert->protect.iv, save_iv, 8 ); - return G10ERR_BAD_PASS; - } + copy_secret_cert( cert, save_cert ); + free_secret_cert( save_cert ); + memcpy( cert->protect.iv, save_iv, 8 ); + return G10ERR_BAD_PASS; } - + /* the checksum may fail, so we also check the key itself */ res = pubkey_check_secret_key( cert->pubkey_algo, cert->skey ); if( res ) { copy_secret_cert( cert, save_cert ); @@ -124,37 +98,11 @@ do_check( PKT_secret_cert *cert ) free_secret_cert( save_cert ); cert->is_protected = 0; } - else { /* not protected */ - switch( cert->pubkey_algo ) { - case PUBKEY_ALGO_ELGAMAL_E: - case PUBKEY_ALGO_ELGAMAL: - csum = checksum_mpi( cert->skey[3] ); - break; - case PUBKEY_ALGO_DSA: - csum = checksum_mpi( cert->skey[4] ); - break; - case PUBKEY_ALGO_RSA_E: - case PUBKEY_ALGO_RSA_S: - case PUBKEY_ALGO_RSA: - csum =0; - buffer = mpi_get_buffer( cert->skey[2], &nbytes, NULL ); - csum += checksum_u16( nbytes*8 ); - csum += checksum( buffer, nbytes ); - m_free( buffer ); - buffer = mpi_get_buffer( cert->skey[3], &nbytes, NULL ); - csum += checksum_u16( nbytes*8 ); - csum += checksum( buffer, nbytes ); - m_free( buffer ); - buffer = mpi_get_buffer( cert->skey[4], &nbytes, NULL ); - csum += checksum_u16( nbytes*8 ); - csum += checksum( buffer, nbytes ); - m_free( buffer ); - buffer = mpi_get_buffer( cert->skey[5], &nbytes, NULL ); - csum += checksum_u16( nbytes*8 ); - csum += checksum( buffer, nbytes ); - m_free( buffer ); - break; - default: BUG(); + else { /* not protected, assume it is okay if the checksum is okay */ + csum = 0; + for(i=pubkey_get_npkey(cert->pubkey_algo); + i < pubkey_get_nskey(cert->pubkey_algo); i++ ) { + csum += checksum_mpi( cert->skey[i] ); } if( csum != cert->csum ) return G10ERR_CHECKSUM; @@ -212,34 +160,6 @@ is_secret_key_protected( PKT_secret_cert *cert ) } -static int -do_protect( void (*fnc)(CIPHER_HANDLE, byte *, byte *, unsigned), - CIPHER_HANDLE fnc_hd, PKT_secret_cert *cert ) -{ - byte *buffer; - unsigned nbytes; - - switch( cert->pubkey_algo ) { - case PUBKEY_ALGO_ELGAMAL_E: - case PUBKEY_ALGO_ELGAMAL: - buffer = mpi_get_buffer( cert->skey[3], &nbytes, NULL ); - (*fnc)( fnc_hd, buffer, buffer, nbytes ); - mpi_set_buffer( cert->skey[3], buffer, nbytes, 0 ); - m_free( buffer ); - break; - - case PUBKEY_ALGO_DSA: - buffer = mpi_get_buffer( cert->skey[4], &nbytes, NULL ); - (*fnc)( fnc_hd, buffer, buffer, nbytes ); - mpi_set_buffer( cert->skey[4], buffer, nbytes, 0 ); - m_free( buffer ); - break; - - default: return G10ERR_PUBKEY_ALGO; - } - return 0; -} - /**************** * Protect the secret key certificate with the passphrase from DEK @@ -247,7 +167,10 @@ do_protect( void (*fnc)(CIPHER_HANDLE, byte *, byte *, unsigned), int protect_secret_key( PKT_secret_cert *cert, DEK *dek ) { - int rc=0; + int i, rc = 0; + byte *buffer; + unsigned nbytes; + u16 csum; if( !dek ) return 0; @@ -263,8 +186,21 @@ protect_secret_key( PKT_secret_cert *cert, DEK *dek ) cipher_setkey( cipher_hd, dek->key, dek->keylen ); cipher_setiv( cipher_hd, NULL ); cipher_encrypt( cipher_hd, cert->protect.iv, cert->protect.iv, 8 ); - if( !do_protect( &cipher_encrypt, cipher_hd, cert ) ) - cert->is_protected = 1; + /* NOTE: we always recalculate the checksum because there are some + * test releases which calculated it wrong */ + csum = 0; + for(i=pubkey_get_npkey(cert->pubkey_algo); + i < pubkey_get_nskey(cert->pubkey_algo); i++ ) { + csum += checksum_mpi_counted_nbits( cert->skey[i] ); + buffer = mpi_get_buffer( cert->skey[i], &nbytes, NULL ); + log_debug("protecing i=%d csum=%04hx nbytes=%u\n", i, csum, nbytes ); + cipher_sync( cipher_hd ); + cipher_encrypt( cipher_hd, buffer, buffer, nbytes ); + mpi_set_buffer( cert->skey[i], buffer, nbytes, 0 ); + m_free( buffer ); + } + cert->csum = csum; + cert->is_protected = 1; cipher_close( cipher_hd ); } } diff --git a/g10/seskey.c b/g10/seskey.c index 25819909c..5b271a2d4 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -144,13 +144,25 @@ do_encode_md( MD_HANDLE md, int algo, size_t len, unsigned nbits, MPI -encode_md_value( MD_HANDLE md, int hash_algo, unsigned nbits ) +encode_md_value( int pubkey_algo, MD_HANDLE md, int hash_algo, unsigned nbits ) { int algo = hash_algo? hash_algo : md_get_algo(md); const byte *asn; size_t asnlen, mdlen; - - asn = md_asn_oid( algo, &asnlen, &mdlen ); - return do_encode_md( md, algo, mdlen, nbits, asn, asnlen ); + MPI frame; + + if( pubkey_algo == PUBKEY_ALGO_DSA ) { + 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 ); + } + else { + asn = md_asn_oid( algo, &asnlen, &mdlen ); + frame = do_encode_md( md, algo, mdlen, nbits, asn, asnlen ); + } + return frame; } diff --git a/g10/sig-check.c b/g10/sig-check.c index 0ef69b7d5..76f0aaca7 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -32,6 +32,11 @@ #include "main.h" #include "status.h" +struct cmp_help_context_s { + PKT_signature *sig; + MD_HANDLE md; +}; + static int do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest ); @@ -62,11 +67,87 @@ signature_check( PKT_signature *sig, MD_HANDLE digest ) } +/**************** + * This function gets called by pubkey_verify() if the algorithm needs it. + */ +static int +cmp_help( void *opaque, MPI result ) +{ + #if 0 /* we do not use this anymore */ + int rc=0, i, j, c, old_enc; + byte *dp; + const byte *asn; + size_t mdlen, asnlen; + struct cmp_help_context_s *ctx = opaque; + PKT_signature *sig = ctx->sig; + MD_HANDLE digest = ctx->md; + + old_enc = 0; + for(i=j=0; (c=mpi_getbyte(result, i)) != -1; i++ ) { + if( !j ) { + if( !i && c != 1 ) + break; + else if( i && c == 0xff ) + ; /* skip the padding */ + else if( i && !c ) + j++; + else + break; + } + else if( ++j == 18 && c != 1 ) + break; + else if( j == 19 && c == 0 ) { + old_enc++; + break; + } + } + if( old_enc ) { + log_error("old encoding scheme is not supported\n"); + return G10ERR_GENERAL; + } + + if( (rc=check_digest_algo(sig->digest_algo)) ) + return rc; /* unsupported algo */ + asn = md_asn_oid( sig->digest_algo, &asnlen, &mdlen ); + + for(i=mdlen,j=asnlen-1; (c=mpi_getbyte(result, i)) != -1 && j >= 0; + i++, j-- ) + if( asn[j] != c ) + break; + if( j != -1 || mpi_getbyte(result, i) ) + return G10ERR_BAD_PUBKEY; /* ASN is wrong */ + for(i++; (c=mpi_getbyte(result, i)) != -1; i++ ) + if( c != 0xff ) + break; + i++; + if( c != sig->digest_algo || mpi_getbyte(result, i) ) { + /* Padding or leading bytes in signature is wrong */ + return G10ERR_BAD_PUBKEY; + } + if( mpi_getbyte(result, mdlen-1) != sig->digest_start[0] + || mpi_getbyte(result, mdlen-2) != sig->digest_start[1] ) { + /* Wrong key used to check the signature */ + return G10ERR_BAD_PUBKEY; + } + + dp = md_read( digest, sig->digest_algo ); + for(i=mdlen-1; i >= 0; i--, dp++ ) { + if( mpi_getbyte( result, i ) != *dp ) + return G10ERR_BAD_SIGN; + } + return 0; + #else + return -1; + #endif +} + + static int do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest ) { MPI result = NULL; int rc=0; + struct cmp_help_context_s ctx; if( pkc->version == 4 && pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) { log_info("this is a PGP generated " @@ -77,169 +158,56 @@ do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest ) if( pkc->timestamp > sig->timestamp ) return G10ERR_TIME_CONFLICT; /* pubkey newer that signature */ - if( is_ELGAMAL(pkc->pubkey_algo) ) { - if( (rc=check_digest_algo(sig->digest_algo)) ) - goto leave; - /* make sure the digest algo is enabled (in case of a detached - * signature */ - md_enable( digest, sig->digest_algo ); - /* complete the digest */ - md_putc( digest, sig->sig_class ); - { u32 a = sig->timestamp; - md_putc( digest, (a >> 24) & 0xff ); - md_putc( digest, (a >> 16) & 0xff ); - md_putc( digest, (a >> 8) & 0xff ); - md_putc( digest, a & 0xff ); - } - md_final( digest ); - result = encode_md_value( digest, sig->digest_algo, - mpi_get_nbits(pkc->pkey[0])); - if( DBG_CIPHER ) - log_mpidump("calc sig frame (elg): ", result); - rc = pubkey_verify( pkc->pubkey_algo, result, sig->data, pkc->pkey ); - } - else if( pkc->pubkey_algo == PUBKEY_ALGO_DSA ) { - if( (rc=check_digest_algo(sig->digest_algo)) ) - goto leave; - /* make sure the digest algo is enabled (in case of a detached - * signature */ - md_enable( digest, sig->digest_algo ); - - /* complete the digest */ - if( sig->version >= 4 ) - md_putc( digest, sig->version ); - md_putc( digest, sig->sig_class ); - if( sig->version < 4 ) { - u32 a = sig->timestamp; - md_putc( digest, (a >> 24) & 0xff ); - md_putc( digest, (a >> 16) & 0xff ); - md_putc( digest, (a >> 8) & 0xff ); - md_putc( digest, a & 0xff ); - } - else { - byte buf[6]; - size_t n; - md_putc( digest, sig->pubkey_algo ); - md_putc( digest, sig->digest_algo ); - if( sig->hashed_data ) { - n = (sig->hashed_data[0] << 8) | sig->hashed_data[1]; - md_write( digest, sig->hashed_data, n+2 ); - n += 6; - } - else - n = 6; - /* add some magic */ - buf[0] = sig->version; - buf[1] = 0xff; - buf[2] = n >> 24; - buf[3] = n >> 16; - buf[4] = n >> 8; - buf[5] = n; - md_write( digest, buf, 6 ); - } - md_final( digest ); - - result = mpi_alloc( (md_digest_length(sig->digest_algo) - +BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB ); - mpi_set_buffer( result, md_read(digest, sig->digest_algo), - md_digest_length(sig->digest_algo), 0 ); - if( DBG_CIPHER ) - log_mpidump("calc sig frame: ", result); - rc = pubkey_verify( pkc->pubkey_algo, result, sig->data, pkc->pkey ); - } - #if 0 /* WORK!!! */ - else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA - || pkc->pubkey_algo == PUBKEY_ALGO_RSA_S ) { - int i, j, c, old_enc; - byte *dp; - const byte *asn; - size_t mdlen, asnlen; - - result = mpi_alloc(40); - rsa_public( result, sig->d.rsa.rsa_integer, &pkc->d.rsa ); - - old_enc = 0; - for(i=j=0; (c=mpi_getbyte(result, i)) != -1; i++ ) { - if( !j ) { - if( !i && c != 1 ) - break; - else if( i && c == 0xff ) - ; /* skip the padding */ - else if( i && !c ) - j++; - else - break; - } - else if( ++j == 18 && c != 1 ) - break; - else if( j == 19 && c == 0 ) { - old_enc++; - break; - } - } - if( old_enc ) { - log_error("old encoding scheme is not supported\n"); - rc = G10ERR_GENERAL; - goto leave; - } - - if( (rc=check_digest_algo(sig->digest_algo)) ) - goto leave; /* unsupported algo */ - md_enable( digest, sig->digest_algo ); - asn = md_asn_oid( sig->digest_algo, &asnlen, &mdlen ); - - for(i=mdlen,j=asnlen-1; (c=mpi_getbyte(result, i)) != -1 && j >= 0; - i++, j-- ) - if( asn[j] != c ) - break; - if( j != -1 || mpi_getbyte(result, i) ) { /* ASN is wrong */ - rc = G10ERR_BAD_PUBKEY; - goto leave; - } - for(i++; (c=mpi_getbyte(result, i)) != -1; i++ ) - if( c != 0xff ) - break; - i++; - if( c != sig->digest_algo || mpi_getbyte(result, i) ) { - /* Padding or leading bytes in signature is wrong */ - rc = G10ERR_BAD_PUBKEY; - goto leave; - } - if( mpi_getbyte(result, mdlen-1) != sig->digest_start[0] - || mpi_getbyte(result, mdlen-2) != sig->digest_start[1] ) { - /* Wrong key used to check the signature */ - rc = G10ERR_BAD_PUBKEY; - goto leave; - } + if( (rc=check_digest_algo(sig->digest_algo)) ) + return rc; + if( (rc=check_pubkey_algo(sig->pubkey_algo)) ) + return rc; - /* complete the digest */ - md_putc( digest, sig->sig_class ); - { u32 a = sig->timestamp; - md_putc( digest, (a >> 24) & 0xff ); - md_putc( digest, (a >> 16) & 0xff ); - md_putc( digest, (a >> 8) & 0xff ); - md_putc( digest, a & 0xff ); - } - md_final( digest ); - dp = md_read( digest, sig->digest_algo ); - for(i=mdlen-1; i >= 0; i--, dp++ ) { - if( mpi_getbyte( result, i ) != *dp ) { - rc = G10ERR_BAD_SIGN; - goto leave; - } - } + /* make sure the digest algo is enabled (in case of a detached signature)*/ + md_enable( digest, sig->digest_algo ); + + /* complete the digest */ + if( sig->version >= 4 ) + md_putc( digest, sig->version ); + md_putc( digest, sig->sig_class ); + if( sig->version < 4 ) { + u32 a = sig->timestamp; + md_putc( digest, (a >> 24) & 0xff ); + md_putc( digest, (a >> 16) & 0xff ); + md_putc( digest, (a >> 8) & 0xff ); + md_putc( digest, a & 0xff ); } - #endif else { - /*log_debug("signature_check: unsupported pubkey algo %d\n", - pkc->pubkey_algo );*/ - rc = G10ERR_PUBKEY_ALGO; - goto leave; + byte buf[6]; + size_t n; + md_putc( digest, sig->pubkey_algo ); + md_putc( digest, sig->digest_algo ); + if( sig->hashed_data ) { + n = (sig->hashed_data[0] << 8) | sig->hashed_data[1]; + md_write( digest, sig->hashed_data, n+2 ); + n += 6; + } + else + n = 6; + /* add some magic */ + buf[0] = sig->version; + buf[1] = 0xff; + buf[2] = n >> 24; + buf[3] = n >> 16; + buf[4] = n >> 8; + buf[5] = n; + md_write( digest, buf, 6 ); } - - - leave: + md_final( digest ); + + result = encode_md_value( pkc->pubkey_algo, digest, sig->digest_algo, + mpi_get_nbits(pkc->pkey[0])); + ctx.sig = sig; + ctx.md = digest; + rc = pubkey_verify( pkc->pubkey_algo, result, sig->data, pkc->pkey, + cmp_help, &ctx ); mpi_free( result ); + return rc; } diff --git a/g10/sign.c b/g10/sign.c index a85f1f952..2505526ce 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -53,14 +53,8 @@ do_sign( PKT_secret_cert *skc, PKT_signature *sig, sig->digest_algo = digest_algo; sig->digest_start[0] = dp[0]; sig->digest_start[1] = dp[1]; - if( skc->pubkey_algo == PUBKEY_ALGO_DSA ) { - frame = mpi_alloc( (md_digest_length(digest_algo)+BYTES_PER_MPI_LIMB-1) - / BYTES_PER_MPI_LIMB ); - mpi_set_buffer( frame, md_read(md, digest_algo), - md_digest_length(digest_algo), 0 ); - } - else - frame = encode_md_value( md, digest_algo, mpi_get_nbits(skc->skey[0])); + frame = encode_md_value( skc->pubkey_algo, md, + digest_algo, mpi_get_nbits(skc->skey[0])); rc = pubkey_sign( skc->pubkey_algo, sig->data, frame, skc->skey ); mpi_free(frame); if( rc ) diff --git a/include/cipher.h b/include/cipher.h index 7913e4a33..6481ceeda 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -29,11 +29,6 @@ #include "mpi.h" #include "../cipher/md.h" -#ifdef HAVE_RSA_CIPHER - #include "../cipher/rsa.h" -#endif -#include "../cipher/elgamal.h" -#include "../cipher/dsa.h" #include "../cipher/random.h" @@ -57,9 +52,7 @@ #define DIGEST_ALGO_MD5 1 #define DIGEST_ALGO_SHA1 2 #define DIGEST_ALGO_RMD160 3 -#ifdef WITH_TIGER_HASH #define DIGEST_ALGO_TIGER 6 -#endif #define is_RSA(a) ((a)==PUBKEY_ALGO_RSA || (a)==PUBKEY_ALGO_RSA_E \ || (a)==PUBKEY_ALGO_RSA_S ) @@ -123,7 +116,8 @@ int pubkey_check_secret_key( int algo, MPI *skey ); int pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ); int pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey ); int pubkey_sign( int algo, MPI *resarr, MPI hash, MPI *skey ); -int pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey ); +int pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey, + int (*cmp)(void *, MPI), void *opaque ); /*-- smallprime.c --*/ extern ushort small_prime_numbers[]; diff --git a/include/g10lib.h b/include/g10lib.h index 12e846ca8..338737831 100644 --- a/include/g10lib.h +++ b/include/g10lib.h @@ -79,6 +79,10 @@ unsigned g10m_get_size( MPI a ); ******* miscellaneous functions ******* *****************************************/ +const char *g10m_revision_string(int mode); +const char *g10c_revision_string(int mode); +const char *g10u_revision_string(int mode); + MPI g10c_generate_secret_prime( unsigned nbits ); unsigned char g10c_get_random_byte( int level ); diff --git a/include/mpi.h b/include/mpi.h index 0725b7d6b..9d93d8505 100644 --- a/include/mpi.h +++ b/include/mpi.h @@ -55,6 +55,7 @@ typedef struct mpi_struct { #define MPI_NULL NULL #define mpi_get_nlimbs(a) ((a)->nlimbs) +#define mpi_get_nbit_info(a) ((a)->nbits) #define mpi_is_neg(a) ((a)->sign) /*-- mpiutil.c --*/ diff --git a/mpi/g10m.c b/mpi/g10m.c index 79d571462..6cad79587 100644 --- a/mpi/g10m.c +++ b/mpi/g10m.c @@ -25,6 +25,9 @@ #define _g10lib_INTERNAL 1 #include "g10lib.h" + +const char *g10m_revision_string(int dummy) { return "$Revision$"; } + MPI g10m_new( unsigned nbits ) { diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c index 2227cfc19..7c661094f 100644 --- a/mpi/mpiutil.c +++ b/mpi/mpiutil.c @@ -252,6 +252,7 @@ mpi_copy( MPI a ) b->nlimbs = a->nlimbs; b->sign = a->sign; b->secure = a->secure; + b->nbits = a->nbits; for(i=0; i < b->nlimbs; i++ ) b->d[i] = a->d[i]; } @@ -273,6 +274,7 @@ mpi_set( MPI w, MPI u) up = u->d; MPN_COPY( wp, up, usize ); w->nlimbs = usize; + w->nbits = u->nbits; w->sign = usign; } @@ -284,6 +286,7 @@ mpi_set_ui( MPI w, unsigned long u) w->d[0] = u; w->nlimbs = u? 1:0; w->sign = 0; + w->nbits = 0; } diff --git a/util/g10u.c b/util/g10u.c index 1b0bc9d4c..16e235e09 100644 --- a/util/g10u.c +++ b/util/g10u.c @@ -25,6 +25,10 @@ #define _g10lib_INTERNAL 1 #include "g10lib.h" + +const char *g10u_revision_string(int dummy) { return "$Revision$"; } + + void *g10_malloc( size_t n ) { return m_alloc( n ); } void *g10_calloc( size_t n ) { return m_alloc_clear( n ); } void *g10_malloc_secure( size_t n ) { return m_alloc_secure( n ); } diff --git a/util/memory.c b/util/memory.c index e3f45be5b..013bd55cc 100644 --- a/util/memory.c +++ b/util/memory.c @@ -127,7 +127,7 @@ add_entry( byte *p, unsigned n, int mode, const char *info, const char *by ) index = memtbl_len++; else { struct memtbl_entry *e; - /* look for a used entry in the table. We take the first one, + /* look for a used entry in the table. We take the first one, * so that freed entries remain as long as possible in the table * (free appends a new one) */ @@ -338,6 +338,7 @@ out_of_core(size_t n, int secure) { log_fatal("out of %s memory while allocating %u bytes\n", secure? "secure":"" ,(unsigned)n ); + } /**************** diff --git a/zlib/Makefile b/zlib/Makefile index 0330f59c5..e3aa756ed 100644 --- a/zlib/Makefile +++ b/zlib/Makefile @@ -91,7 +91,7 @@ POSUB = po RANLIB = ranlib USE_INCLUDED_LIBINTL = yes USE_NLS = yes -VERSION = 0.2.19a +VERSION = 0.2.19b ZLIBS = l = |