From e662bf708b4f24ec36b4ec8d26e66e4381bddeda Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Sat, 13 Jun 1998 17:00:02 +0000 Subject: [PATCH] gnupg extension are now working --- cipher/ChangeLog | 12 +- cipher/Makefile.am | 2 +- cipher/blowfish.c | 36 +-- cipher/cipher.c | 3 +- cipher/dsa.c | 192 +++++++++++--- cipher/dsa.h | 33 +-- cipher/dynload.c | 120 +++++++-- cipher/dynload.h | 11 + cipher/elgamal.c | 229 +++++++++++++--- cipher/elgamal.h | 34 +-- cipher/g10c.c | 43 +++ cipher/md.c | 70 +++++ cipher/md.h | 3 + cipher/misc.c | 175 ------------ cipher/primegen.c | 2 + cipher/pubkey.c | 645 ++++++++++++++++++++++++++------------------- doc/DETAILS | 2 +- g10/g10.c | 15 +- g10/getkey.c | 10 +- g10/keydb.h | 3 +- g10/keygen.c | 52 ++-- g10/parse-packet.c | 9 +- g10/seckey-cert.c | 66 ++--- g10/sig-check.c | 6 +- g10/trustdb.c | 19 +- include/ChangeLog | 4 + include/cipher.h | 22 +- include/distfiles | 2 + include/g10lib.h | 174 ++++++++++++ mpi/Makefile.am | 3 +- mpi/g10m.c | 90 +++++++ util/Makefile.am | 2 +- util/g10u.c | 35 +++ 33 files changed, 1411 insertions(+), 713 deletions(-) create mode 100644 cipher/g10c.c delete mode 100644 cipher/misc.c create mode 100644 include/g10lib.h create mode 100644 mpi/g10m.c create mode 100644 util/g10u.c diff --git a/cipher/ChangeLog b/cipher/ChangeLog index 6e59455a9..760f52d40 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,7 +1,15 @@ +Sat Jun 13 14:16:57 1998 Werner Koch (wk@isil.d.shuttle.de) + + * pubkey.c: Major changes to allow extensions. Changed the inteface + of all public key ciphers and added the ability to load extensions + on demand. + + * misc.c: Removed. + Wed Jun 10 07:52:08 1998 Werner Koch,mobil,,, (wk@tobold) - * dynload.c: New - * cipher.c: Major changes to allow extensions. + * dynload.c: New. + * cipher.c: Major changes to allow extensions. Mon Jun 8 22:43:00 1998 Werner Koch (wk@isil.d.shuttle.de) diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 53ba749a8..04d1ef8ed 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -35,7 +35,7 @@ libcipher_a_SOURCES = cipher.c \ sha1.c \ dsa.h \ dsa.c \ - misc.c \ + g10c.c \ smallprime.c diff --git a/cipher/blowfish.c b/cipher/blowfish.c index ec686e1ee..65a408ef8 100644 --- a/cipher/blowfish.c +++ b/cipher/blowfish.c @@ -55,9 +55,9 @@ typedef struct { u32 p[BLOWFISH_ROUNDS+2]; } BLOWFISH_context; -static void blowfish_setkey( BLOWFISH_context *c, byte *key, unsigned keylen ); -static void blowfish_encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ); -static void blowfish_decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ); +static void setkey( BLOWFISH_context *c, byte *key, unsigned keylen ); +static void encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ); +static void decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ); /* precomputed S boxes */ @@ -414,7 +414,7 @@ decrypt( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr ) #undef R static void -blowfish_encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) +encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) { u32 d1, d2; @@ -433,7 +433,7 @@ blowfish_encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) static void -blowfish_decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) +decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) { u32 d1, d2; @@ -461,19 +461,19 @@ selftest() byte key3[] = { 0x41, 0x79, 0x6E, 0xA0, 0x52, 0x61, 0x6E, 0xE4 }; byte cipher3[] = { 0xE1, 0x13, 0xF4, 0x10, 0x2C, 0xFC, 0xCE, 0x43 }; - blowfish_setkey( &c, "abcdefghijklmnopqrstuvwxyz", 26 ); - blowfish_encrypt_block( &c, buffer, plain ); + setkey( &c, "abcdefghijklmnopqrstuvwxyz", 26 ); + encrypt_block( &c, buffer, plain ); if( memcmp( buffer, "\x32\x4E\xD0\xFE\xF4\x13\xA2\x03", 8 ) ) log_error("wrong blowfish encryption\n"); - blowfish_decrypt_block( &c, buffer, buffer ); + decrypt_block( &c, buffer, buffer ); if( memcmp( buffer, plain, 8 ) ) log_bug("blowfish failed\n"); - blowfish_setkey( &c, key3, 8 ); - blowfish_encrypt_block( &c, buffer, plain3 ); + setkey( &c, key3, 8 ); + encrypt_block( &c, buffer, plain3 ); if( memcmp( buffer, cipher3, 8 ) ) log_error("wrong blowfish encryption (3)\n"); - blowfish_decrypt_block( &c, buffer, buffer ); + decrypt_block( &c, buffer, buffer ); if( memcmp( buffer, plain3, 8 ) ) log_bug("blowfish failed (3)\n"); } @@ -481,7 +481,7 @@ selftest() static void -blowfish_setkey( BLOWFISH_context *c, byte *key, unsigned keylen ) +setkey( BLOWFISH_context *c, byte *key, unsigned keylen ) { int i, j; u32 data, datal, datar; @@ -555,17 +555,17 @@ blowfish_setkey( BLOWFISH_context *c, byte *key, unsigned keylen ) const char * blowfish_get_info( int algo, size_t *keylen, size_t *blocksize, size_t *contextsize, - void (**setkey)( void *c, byte *key, unsigned keylen ), - void (**encrypt)( void *c, byte *outbuf, byte *inbuf ), - void (**decrypt)( void *c, byte *outbuf, byte *inbuf ) + void (**r_setkey)( void *c, byte *key, unsigned keylen ), + void (**r_encrypt)( void *c, byte *outbuf, byte *inbuf ), + void (**r_decrypt)( void *c, byte *outbuf, byte *inbuf ) ) { *keylen = algo == CIPHER_ALGO_BLOWFISH ? 128 : 160; *blocksize = BLOWFISH_BLOCKSIZE; *contextsize = sizeof(BLOWFISH_context); - *setkey = FNCCAST_SETKEY(blowfish_setkey); - *encrypt= FNCCAST_CRYPT(blowfish_encrypt_block); - *decrypt= FNCCAST_CRYPT(blowfish_decrypt_block); + *r_setkey = FNCCAST_SETKEY(setkey); + *r_encrypt= FNCCAST_CRYPT(encrypt_block); + *r_decrypt= FNCCAST_CRYPT(decrypt_block); if( algo == CIPHER_ALGO_BLOWFISH ) return "BLOWFISH"; diff --git a/cipher/cipher.c b/cipher/cipher.c index 6ac468274..064947865 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -178,7 +178,8 @@ load_cipher_modules() continue; } /* put it into the table */ - log_info("loaded cipher %d (%s)\n", ct->algo, name); + if( g10_opt_verbose > 1 ) + log_info("loaded cipher %d (%s)\n", ct->algo, name); ct->name = name; ct_idx++; ct++; diff --git a/cipher/dsa.c b/cipher/dsa.c index d1c15c41c..20011da38 100644 --- a/cipher/dsa.c +++ b/cipher/dsa.c @@ -28,6 +28,30 @@ #include "cipher.h" #include "dsa.h" +typedef struct { + MPI p; /* prime */ + MPI q; /* group order */ + MPI g; /* group generator */ + MPI y; /* g^x mod p */ +} DSA_public_key; + + +typedef struct { + MPI p; /* prime */ + MPI q; /* group order */ + MPI g; /* group generator */ + MPI y; /* g^x mod p */ + MPI x; /* secret exponent */ +} DSA_secret_key; + + +static MPI gen_k( MPI q ); +static void test_keys( DSA_secret_key *sk, unsigned qbits ); +static int check_secret_key( DSA_secret_key *sk ); +static void generate( DSA_secret_key *sk, unsigned nbits, MPI **ret_factors ); +static void sign(MPI r, MPI s, MPI input, DSA_secret_key *skey); +static int verify(MPI r, MPI s, MPI input, DSA_public_key *pkey); + /**************** * Generate a random secret exponent k less than q */ @@ -55,37 +79,23 @@ gen_k( MPI q ) return k; } -void -dsa_free_public_key( DSA_public_key *pk ) -{ - mpi_free( pk->p ); pk->p = NULL; - mpi_free( pk->q ); pk->q = NULL; - mpi_free( pk->g ); pk->g = NULL; - mpi_free( pk->y ); pk->y = NULL; -} - -void -dsa_free_secret_key( DSA_secret_key *sk ) -{ - mpi_free( sk->p ); sk->p = NULL; - mpi_free( sk->q ); sk->q = NULL; - mpi_free( sk->g ); sk->g = NULL; - mpi_free( sk->y ); sk->y = NULL; - mpi_free( sk->x ); sk->x = NULL; -} - static void -test_keys( DSA_public_key *pk, DSA_secret_key *sk, unsigned qbits ) +test_keys( DSA_secret_key *sk, unsigned qbits ) { + DSA_public_key pk; MPI test = mpi_alloc( qbits / BITS_PER_MPI_LIMB ); MPI out1_a = mpi_alloc( qbits / BITS_PER_MPI_LIMB ); MPI out1_b = mpi_alloc( qbits / BITS_PER_MPI_LIMB ); + pk.p = sk->p; + pk.q = sk->q; + pk.g = sk->g; + pk.y = sk->y; mpi_set_bytes( test, qbits, get_random_byte, 0 ); - dsa_sign( out1_a, out1_b, test, sk ); - if( !dsa_verify( out1_a, out1_b, test, pk ) ) + sign( out1_a, out1_b, test, sk ); + if( !verify( out1_a, out1_b, test, &pk ) ) log_fatal("DSA:: sign, verify failed\n"); mpi_free( test ); @@ -100,9 +110,8 @@ test_keys( DSA_public_key *pk, DSA_secret_key *sk, unsigned qbits ) * Returns: 2 structures filled with all needed values * and an array with the n-1 factors of (p-1) */ -void -dsa_generate( DSA_public_key *pk, DSA_secret_key *sk, - unsigned nbits, MPI **ret_factors ) +static void +generate( DSA_secret_key *sk, unsigned nbits, MPI **ret_factors ) { MPI p; /* the prime */ MPI q; /* the 160 bit prime factor */ @@ -176,10 +185,6 @@ dsa_generate( DSA_public_key *pk, DSA_secret_key *sk, } /* copy the stuff to the key structures */ - pk->p = mpi_copy(p); - pk->q = mpi_copy(q); - pk->g = mpi_copy(g); - pk->y = mpi_copy(y); sk->p = p; sk->q = q; sk->g = g; @@ -187,7 +192,7 @@ dsa_generate( DSA_public_key *pk, DSA_secret_key *sk, sk->x = x; /* now we can test our keys (this should never fail!) */ - test_keys( pk, sk, qbits ); + test_keys( sk, qbits ); } @@ -196,8 +201,8 @@ dsa_generate( DSA_public_key *pk, DSA_secret_key *sk, * Test whether the secret key is valid. * Returns: if this is a valid key. */ -int -dsa_check_secret_key( DSA_secret_key *sk ) +static int +check_secret_key( DSA_secret_key *sk ) { int rc; MPI y = mpi_alloc( mpi_get_nlimbs(sk->y) ); @@ -214,8 +219,8 @@ dsa_check_secret_key( DSA_secret_key *sk ) * Make a DSA signature from HASH and put it into r and s. */ -void -dsa_sign(MPI r, MPI s, MPI hash, DSA_secret_key *skey ) +static void +sign(MPI r, MPI s, MPI hash, DSA_secret_key *skey ) { MPI k; MPI kinv; @@ -247,8 +252,8 @@ dsa_sign(MPI r, MPI s, MPI hash, DSA_secret_key *skey ) /**************** * Returns true if the signature composed from R and S is valid. */ -int -dsa_verify(MPI r, MPI s, MPI hash, DSA_public_key *pkey ) +static int +verify(MPI r, MPI s, MPI hash, DSA_public_key *pkey ) { int rc; MPI w, u1, u2, v; @@ -290,3 +295,118 @@ dsa_verify(MPI r, MPI s, MPI hash, DSA_public_key *pkey ) return rc; } + +/********************************************* + ************** interface ****************** + *********************************************/ + +int +dsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ) +{ + DSA_secret_key sk; + + if( algo != PUBKEY_ALGO_DSA ) + return G10ERR_PUBKEY_ALGO; + + generate( &sk, nbits, retfactors ); + skey[0] = sk.p; + skey[1] = sk.q; + skey[2] = sk.g; + skey[3] = sk.y; + skey[4] = sk.x; + return 0; +} + + +int +dsa_check_secret_key( int algo, MPI *skey ) +{ + DSA_secret_key sk; + + if( algo != PUBKEY_ALGO_DSA ) + return G10ERR_PUBKEY_ALGO; + + sk.p = skey[0]; + sk.q = skey[1]; + sk.g = skey[2]; + sk.y = skey[3]; + sk.x = skey[4]; + if( !check_secret_key( &sk ) ) + return G10ERR_BAD_SECKEY; + + return 0; +} + + + +int +dsa_sign( int algo, MPI *resarr, MPI data, MPI *skey ) +{ + DSA_secret_key sk; + + if( algo != PUBKEY_ALGO_DSA ) + return G10ERR_PUBKEY_ALGO; + + sk.p = skey[0]; + sk.q = skey[1]; + sk.g = skey[2]; + sk.y = skey[3]; + sk.x = skey[4]; + resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); + resarr[1] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); + sign( resarr[0], resarr[1], data, &sk ); + return 0; +} + +int +dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey ) +{ + DSA_public_key pk; + + if( algo != PUBKEY_ALGO_DSA ) + return G10ERR_PUBKEY_ALGO; + + pk.p = pkey[0]; + pk.q = pkey[1]; + pk.g = pkey[2]; + pk.y = pkey[3]; + if( !verify( data[0], data[1], hash, &pk ) ) + return G10ERR_BAD_SIGN; + return 0; +} + + + +unsigned +dsa_get_nbits( int algo, MPI *pkey ) +{ + if( algo != PUBKEY_ALGO_DSA ) + return 0; + return mpi_get_nbits( pkey[0] ); +} + + +/**************** + * Return some information about the algorithm. We need algo here to + * distinguish different flavors of the algorithm. + * Returns: A pointer to string describing the algorithm or NULL if + * the ALGO is invalid. + * Usage: Bit 0 set : allows signing + * 1 set : allows encryption + */ +const char * +dsa_get_info( int algo, int *npkey, int *nskey, int *nenc, int *nsig, + int *usage ) +{ + *npkey = 4; + *nskey = 5; + *nenc = 0; + *nsig = 2; + + switch( algo ) { + case PUBKEY_ALGO_DSA: *usage = 1; return "DSA"; + default: *usage = 0; return NULL; + } +} + + diff --git a/cipher/dsa.h b/cipher/dsa.h index 2d38a7388..fe977a645 100644 --- a/cipher/dsa.h +++ b/cipher/dsa.h @@ -20,31 +20,12 @@ #ifndef G10_DSA_H #define G10_DSA_H -#include "mpi.h" - -typedef struct { - MPI p; /* prime */ - MPI q; /* group order */ - MPI g; /* group generator */ - MPI y; /* g^x mod p */ -} DSA_public_key; - - -typedef struct { - MPI p; /* prime */ - MPI q; /* group order */ - MPI g; /* group generator */ - MPI y; /* g^x mod p */ - MPI x; /* secret exponent */ -} DSA_secret_key; - - -void dsa_free_public_key( DSA_public_key *pk ); -void dsa_free_secret_key( DSA_secret_key *sk ); -int dsa_check_secret_key( DSA_secret_key *sk ); -void dsa_generate( DSA_public_key *pk, DSA_secret_key *sk, - unsigned nbits, MPI **ret_factors ); -void dsa_sign(MPI r, MPI s, MPI input, DSA_secret_key *skey); -int dsa_verify(MPI r, MPI s, MPI input, DSA_public_key *pkey); +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 ); +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 ); #endif /*G10_DSA_H*/ diff --git a/cipher/dynload.c b/cipher/dynload.c index b40eb4056..e0b2e77e3 100644 --- a/cipher/dynload.c +++ b/cipher/dynload.c @@ -71,11 +71,12 @@ register_cipher_extension( const char *fname ) /* check that it is not already registered */ for(r = extensions; r; r = r->next ) if( !compare_filenames(r->name, el->name) ) { - log_debug("extension '%s' already registered\n", el->name ); + log_info("extension '%s' already registered\n", el->name ); m_free(el); return; } - log_debug("extension '%s' registered\n", el->name ); + if( DBG_CIPHER ) + log_debug("extension '%s' registered\n", el->name ); /* and register */ el->next = extensions; extensions = el; @@ -91,7 +92,7 @@ load_extension( EXTLIST el ) int seq = 0; int class, vers; - el->handle = dlopen(el->name, RTLD_LAZY); + el->handle = dlopen(el->name, RTLD_NOW); if( !el->handle ) { log_error("%s: error loading extension: %s\n", el->name, dlerror() ); goto failure; @@ -102,7 +103,8 @@ load_extension( EXTLIST el ) goto failure; } - log_info("%s: version '%s'\n", el->name, *name ); + if( g10_opt_verbose ) + log_info("%s: version '%s'\n", el->name, *name ); sym = dlsym(el->handle, "gnupgext_enum_func"); if( (err=dlerror()) ) { @@ -111,23 +113,26 @@ load_extension( EXTLIST el ) } el->enumfunc = (void *(*)(int,int*,int*,int*))sym; - /* list the contents of the module */ - while( (sym = (*el->enumfunc)(0, &seq, &class, &vers)) ) { - if( vers != 1 ) { - log_error("%s: ignoring func with version %d\n", el->name, vers); - continue; - } - switch( class ) { - case 11: - case 21: - case 31: - log_info("%s: provides %s algorithm %d\n", el->name, - class == 11? "md" : - class == 21? "cipher" : "pubkey", - *(int*)sym); - break; - default: - log_debug("%s: skipping class %d\n", el->name, class); + if( g10_opt_verbose > 1 ) { + /* list the contents of the module */ + while( (sym = (*el->enumfunc)(0, &seq, &class, &vers)) ) { + if( vers != 1 ) { + log_info("%s: ignoring func with version %d\n",el->name,vers); + continue; + } + switch( class ) { + case 11: + case 21: + case 31: + log_info("%s: provides %s algorithm %d\n", el->name, + class == 11? "md" : + class == 21? "cipher" : "pubkey", + *(int*)sym); + break; + default: + /*log_debug("%s: skipping class %d\n", el->name, class);*/ + break; + } } } return 0; @@ -195,7 +200,78 @@ enum_gnupgext_ciphers( void **enum_context, int *algo, *algo = *(int*)sym; algname = (*finfo)( *algo, keylen, blocksize, contextsize, setkey, encrypt, decrypt ); - log_debug("found algo %d (%s)\n", *algo, algname ); + if( algname ) { + ctx->r = r; + return algname; + } + } + ctx->seq2 = 0; + } + ctx->seq1 = 0; + } + ctx->r = r; + return NULL; +} + +const char * +enum_gnupgext_pubkeys( void **enum_context, int *algo, + int *npkey, int *nskey, int *nenc, int *nsig, int *usage, + int (**generate)( int algo, unsigned nbits, MPI *skey, MPI **retfactors ), + int (**check_secret_key)( int algo, MPI *skey ), + 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 ), + unsigned (**get_nbits)( int algo, MPI *pkey ) ) +{ + EXTLIST r; + ENUMCONTEXT *ctx; + const char * (*finfo)( int, int *, int *, int *, int *, int *, + int (**)( int, unsigned, MPI *, MPI **), + int (**)( int, MPI * ), + int (**)( int, MPI *, MPI , MPI * ), + int (**)( int, MPI *, MPI *, MPI * ), + int (**)( int, MPI *, MPI , MPI * ), + int (**)( int, MPI , MPI *, MPI * ), + unsigned (**)( int , MPI * ) ); + + if( !*enum_context ) { /* init context */ + ctx = m_alloc_clear( sizeof( *ctx ) ); + ctx->r = extensions; + *enum_context = ctx; + } + else if( !algo ) { /* release the context */ + m_free(*enum_context); + *enum_context = NULL; + return NULL; + } + else + ctx = *enum_context; + + for( r = ctx->r; r; r = r->next ) { + int class, vers; + + if( r->failed ) + continue; + if( !r->handle && load_extension(r) ) + continue; + /* get a pubkey info function */ + if( ctx->sym ) + goto inner_loop; + while( (ctx->sym = (*r->enumfunc)(30, &ctx->seq1, &class, &vers)) ) { + void *sym; + if( vers != 1 || class != 30 ) + continue; + inner_loop: + finfo = ctx->sym; + while( (sym = (*r->enumfunc)(31, &ctx->seq2, &class, &vers)) ) { + const char *algname; + if( vers != 1 || class != 31 ) + continue; + *algo = *(int*)sym; + algname = (*finfo)( *algo, npkey, nskey, nenc, nsig, usage, + generate, check_secret_key, encrypt, + decrypt, sign, verify, get_nbits ); if( algname ) { ctx->r = r; return algname; diff --git a/cipher/dynload.h b/cipher/dynload.h index 78f41c644..69b5d8fa9 100644 --- a/cipher/dynload.h +++ b/cipher/dynload.h @@ -28,4 +28,15 @@ enum_gnupgext_ciphers( void **enum_context, int *algo, void (**decrypt)( void *c, byte *outbuf, byte *inbuf ) ); +const char * +enum_gnupgext_pubkeys( void **enum_context, int *algo, + int *npkey, int *nskey, int *nenc, int *nsig, int *usage, + int (**generate)( int algo, unsigned nbits, MPI *skey, MPI **retfactors ), + int (**check_secret_key)( int algo, MPI *skey ), + 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 ), + unsigned (**get_nbits)( int algo, MPI *pkey ) ); + #endif /*G10_CIPHER_DYNLOAD_H*/ diff --git a/cipher/elgamal.c b/cipher/elgamal.c index 7fad35c56..b37c756cf 100644 --- a/cipher/elgamal.c +++ b/cipher/elgamal.c @@ -31,42 +31,53 @@ #include "cipher.h" #include "elgamal.h" +typedef struct { + MPI p; /* prime */ + MPI g; /* group generator */ + MPI y; /* g^x mod p */ +} ELG_public_key; -void -elg_free_public_key( ELG_public_key *pk ) -{ - mpi_free( pk->p ); pk->p = NULL; - mpi_free( pk->g ); pk->g = NULL; - mpi_free( pk->y ); pk->y = NULL; -} -void -elg_free_secret_key( ELG_secret_key *sk ) -{ - mpi_free( sk->p ); sk->p = NULL; - mpi_free( sk->g ); sk->g = NULL; - mpi_free( sk->y ); sk->y = NULL; - mpi_free( sk->x ); sk->x = NULL; -} +typedef struct { + MPI p; /* prime */ + MPI g; /* group generator */ + MPI y; /* g^x mod p */ + MPI x; /* secret exponent */ +} ELG_secret_key; + + +static void test_keys( ELG_secret_key *sk, unsigned nbits ); +static MPI gen_k( MPI p ); +static void generate( ELG_secret_key *sk, unsigned nbits, MPI **factors ); +static int check_secret_key( ELG_secret_key *sk ); +static void encrypt(MPI a, MPI b, MPI input, ELG_public_key *pkey ); +static void decrypt(MPI output, MPI a, MPI b, ELG_secret_key *skey ); +static void sign(MPI a, MPI b, MPI input, ELG_secret_key *skey); +static int verify(MPI a, MPI b, MPI input, ELG_public_key *pkey); static void -test_keys( ELG_public_key *pk, ELG_secret_key *sk, unsigned nbits ) +test_keys( ELG_secret_key *sk, unsigned nbits ) { + ELG_public_key pk; MPI test = mpi_alloc( nbits / BITS_PER_MPI_LIMB ); MPI out1_a = mpi_alloc( nbits / BITS_PER_MPI_LIMB ); MPI out1_b = mpi_alloc( nbits / BITS_PER_MPI_LIMB ); MPI out2 = mpi_alloc( nbits / BITS_PER_MPI_LIMB ); + pk.p = sk->p; + pk.g = sk->g; + pk.y = sk->y; + mpi_set_bytes( test, nbits, get_random_byte, 0 ); - elg_encrypt( out1_a, out1_b, test, pk ); - elg_decrypt( out2, out1_a, out1_b, sk ); + encrypt( out1_a, out1_b, test, &pk ); + decrypt( out2, out1_a, out1_b, sk ); if( mpi_cmp( test, out2 ) ) log_fatal("ElGamal operation: encrypt, decrypt failed\n"); - elg_sign( out1_a, out1_b, test, sk ); - if( !elg_verify( out1_a, out1_b, test, pk ) ) + sign( out1_a, out1_b, test, sk ); + if( !verify( out1_a, out1_b, test, &pk ) ) log_fatal("ElGamal operation: sign, verify failed\n"); mpi_free( test ); @@ -115,9 +126,8 @@ gen_k( MPI p ) * Returns: 2 structures filles with all needed values * and an array with n-1 factors of (p-1) */ -void -elg_generate( ELG_public_key *pk, ELG_secret_key *sk, - unsigned nbits, MPI **ret_factors ) +static void +generate( ELG_secret_key *sk, unsigned nbits, MPI **ret_factors ) { MPI p; /* the prime */ MPI p_min1; @@ -186,16 +196,13 @@ elg_generate( ELG_public_key *pk, ELG_secret_key *sk, } /* copy the stuff to the key structures */ - pk->p = mpi_copy(p); - pk->g = mpi_copy(g); - pk->y = mpi_copy(y); sk->p = p; sk->g = g; sk->y = y; sk->x = x; /* now we can test our keys (this should never fail!) */ - test_keys( pk, sk, nbits - 64 ); + test_keys( sk, nbits - 64 ); mpi_free( p_min1 ); mpi_free( temp ); @@ -206,8 +213,8 @@ elg_generate( ELG_public_key *pk, ELG_secret_key *sk, * Test whether the secret key is valid. * Returns: if this is a valid key. */ -int -elg_check_secret_key( ELG_secret_key *sk ) +static int +check_secret_key( ELG_secret_key *sk ) { int rc; MPI y = mpi_alloc( mpi_get_nlimbs(sk->y) ); @@ -219,8 +226,8 @@ elg_check_secret_key( ELG_secret_key *sk ) } -void -elg_encrypt(MPI a, MPI b, MPI input, ELG_public_key *pkey ) +static void +encrypt(MPI a, MPI b, MPI input, ELG_public_key *pkey ) { MPI k; @@ -249,8 +256,8 @@ elg_encrypt(MPI a, MPI b, MPI input, ELG_public_key *pkey ) -void -elg_decrypt(MPI output, MPI a, MPI b, ELG_secret_key *skey ) +static void +decrypt(MPI output, MPI a, MPI b, ELG_secret_key *skey ) { MPI t1 = mpi_alloc_secure( mpi_get_nlimbs( skey->p ) ); @@ -276,8 +283,8 @@ elg_decrypt(MPI output, MPI a, MPI b, ELG_secret_key *skey ) * Make an Elgamal signature out of INPUT */ -void -elg_sign(MPI a, MPI b, MPI input, ELG_secret_key *skey ) +static void +sign(MPI a, MPI b, MPI input, ELG_secret_key *skey ) { MPI k; MPI t = mpi_alloc( mpi_get_nlimbs(a) ); @@ -322,8 +329,8 @@ elg_sign(MPI a, MPI b, MPI input, ELG_secret_key *skey ) /**************** * Returns true if the signature composed of A and B is valid. */ -int -elg_verify(MPI a, MPI b, MPI input, ELG_public_key *pkey ) +static int +verify(MPI a, MPI b, MPI input, ELG_public_key *pkey ) { int rc; MPI t1; @@ -375,3 +382,151 @@ elg_verify(MPI a, MPI b, MPI input, ELG_public_key *pkey ) return rc; } +/********************************************* + ************** interface ****************** + *********************************************/ + +int +elg_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ) +{ + ELG_secret_key sk; + + if( !is_ELGAMAL(algo) ) + return G10ERR_PUBKEY_ALGO; + + generate( &sk, nbits, retfactors ); + skey[0] = sk.p; + skey[1] = sk.g; + skey[2] = sk.y; + skey[3] = sk.x; + return 0; +} + + +int +elg_check_secret_key( int algo, MPI *skey ) +{ + ELG_secret_key sk; + + if( !is_ELGAMAL(algo) ) + return G10ERR_PUBKEY_ALGO; + + sk.p = skey[0]; + sk.g = skey[1]; + sk.y = skey[2]; + sk.x = skey[3]; + if( !check_secret_key( &sk ) ) + return G10ERR_BAD_SECKEY; + + return 0; +} + + + +int +elg_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) +{ + ELG_public_key pk; + + if( !is_ELGAMAL(algo) ) + return G10ERR_PUBKEY_ALGO; + + pk.p = pkey[0]; + pk.g = pkey[1]; + pk.y = pkey[2]; + resarr[0] = mpi_alloc( mpi_get_nlimbs( pk.p ) ); + resarr[1] = mpi_alloc( mpi_get_nlimbs( pk.p ) ); + encrypt( resarr[0], resarr[1], data, &pk ); + return 0; +} + +int +elg_decrypt( int algo, MPI *result, MPI *data, MPI *skey ) +{ + ELG_secret_key sk; + + if( !is_ELGAMAL(algo) ) + return G10ERR_PUBKEY_ALGO; + + sk.p = skey[0]; + sk.g = skey[1]; + sk.y = skey[2]; + sk.x = skey[3]; + *result = mpi_alloc_secure( mpi_get_nlimbs( sk.p ) ); + decrypt( *result, data[0], data[1], &sk ); + return 0; +} + +int +elg_sign( int algo, MPI *resarr, MPI data, MPI *skey ) +{ + ELG_secret_key sk; + + if( !is_ELGAMAL(algo) ) + return G10ERR_PUBKEY_ALGO; + + sk.p = skey[0]; + sk.g = skey[1]; + sk.y = skey[2]; + sk.x = skey[3]; + resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); + resarr[1] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); + sign( resarr[0], resarr[1], data, &sk ); + return 0; +} + +int +elg_verify( int algo, MPI hash, MPI *data, MPI *pkey ) +{ + ELG_public_key pk; + + if( !is_ELGAMAL(algo) ) + return G10ERR_PUBKEY_ALGO; + + pk.p = pkey[0]; + pk.g = pkey[1]; + pk.y = pkey[2]; + if( !verify( data[0], data[1], hash, &pk ) ) + return G10ERR_BAD_SIGN; + return 0; +} + + + +unsigned +elg_get_nbits( int algo, MPI *pkey ) +{ + if( !is_ELGAMAL(algo) ) + return 0; + return mpi_get_nbits( pkey[0] ); +} + + +/**************** + * Return some information about the algorithm. We need algo here to + * distinguish different flavors of the algorithm. + * Returns: A pointer to string describing the algorithm or NULL if + * the ALGO is invalid. + * Usage: Bit 0 set : allows signing + * 1 set : allows encryption + * NOTE: This function allows signing also for ELG-E, chich is not + * okay but a bad hack to allow to work with olf gpg keys. The real check + * is done in the gnupg ocde depending on the packet version. + */ +const char * +elg_get_info( int algo, int *npkey, int *nskey, int *nenc, int *nsig, + int *usage ) +{ + *npkey = 3; + *nskey = 4; + *nenc = 2; + *nsig = 2; + + switch( algo ) { + case PUBKEY_ALGO_ELGAMAL: *usage = 2|1; return "ELG"; + case PUBKEY_ALGO_ELGAMAL_E: *usage = 2|1; return "ELG-E"; + default: *usage = 0; return NULL; + } +} + + diff --git a/cipher/elgamal.h b/cipher/elgamal.h index d253fbd92..a4668ff9d 100644 --- a/cipher/elgamal.h +++ b/cipher/elgamal.h @@ -20,31 +20,15 @@ #ifndef G10_ELGAMAL_H #define G10_ELGAMAL_H -#include "mpi.h" +int elg_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ); +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 ); +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 ); -typedef struct { - MPI p; /* prime */ - MPI g; /* group generator */ - MPI y; /* g^x mod p */ -} ELG_public_key; - - -typedef struct { - MPI p; /* prime */ - MPI g; /* group generator */ - MPI y; /* g^x mod p */ - MPI x; /* secret exponent */ -} ELG_secret_key; - - -void elg_free_public_key( ELG_public_key *pk ); -void elg_free_secret_key( ELG_secret_key *sk ); -void elg_generate( ELG_public_key *pk, ELG_secret_key *sk, - unsigned nbits, MPI **factors ); -int elg_check_secret_key( ELG_secret_key *sk ); -void elg_encrypt(MPI a, MPI b, MPI input, ELG_public_key *pkey ); -void elg_decrypt(MPI output, MPI a, MPI b, ELG_secret_key *skey ); -void elg_sign(MPI a, MPI b, MPI input, ELG_secret_key *skey); -int elg_verify(MPI a, MPI b, MPI input, ELG_public_key *pkey); #endif /*G10_ELGAMAL_H*/ diff --git a/cipher/g10c.c b/cipher/g10c.c new file mode 100644 index 000000000..c6f94022b --- /dev/null +++ b/cipher/g10c.c @@ -0,0 +1,43 @@ +/* g10c.c - Wrapper for cipher functions + * 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 + */ + +#include +#include +#include +#include "mpi.h" +#include "random.h" +#include "cipher.h" +#define _g10lib_INTERNAL 1 +#include "g10lib.h" + + +MPI +g10c_generate_secret_prime( unsigned nbits ) +{ + return generate_secret_prime( nbits ); +} + +byte +g10c_get_random_byte( int level ) +{ + return get_random_byte( level ); +} + + diff --git a/cipher/md.c b/cipher/md.c index 4341b3968..30d7e255d 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -27,6 +27,76 @@ #include "cipher.h" #include "errors.h" + + +/* Note: the first string is the one used by ascii armor */ +static struct { const char *name; int algo;} digest_names[] = { + { "MD5", DIGEST_ALGO_MD5 }, + { "SHA1", DIGEST_ALGO_SHA1 }, + { "SHA-1", DIGEST_ALGO_SHA1 }, + { "RIPEMD160", DIGEST_ALGO_RMD160 }, + { "RMD160", DIGEST_ALGO_RMD160 }, + { "RMD-160", DIGEST_ALGO_RMD160 }, + { "RIPE-MD-160", DIGEST_ALGO_RMD160 }, + { "TIGER", DIGEST_ALGO_TIGER }, + {NULL} }; + + + + +/**************** + * Map a string to the digest algo + */ +int +string_to_digest_algo( const char *string ) +{ + int i; + const char *s; + + for(i=0; (s=digest_names[i].name); i++ ) + if( !stricmp( s, string ) ) + return digest_names[i].algo; + return 0; +} + + +/**************** + * Map a digest algo to a string + */ +const char * +digest_algo_to_string( int algo ) +{ + int i; + + for(i=0; digest_names[i].name; i++ ) + if( digest_names[i].algo == algo ) + return digest_names[i].name; + return NULL; +} + + +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: + return 0; + default: + return G10ERR_DIGEST_ALGO; + } +} + + + + + + + /**************** * Open a message digest handle for use with algorithm ALGO. * More algorithms may be added by md_enable(). The initial algorithm diff --git a/cipher/md.h b/cipher/md.h index e55a99ee0..2d45a1273 100644 --- a/cipher/md.h +++ b/cipher/md.h @@ -55,6 +55,9 @@ typedef struct { } while(0) /*-- md.c --*/ +int string_to_digest_algo( const char *string ); +const char * digest_algo_to_string( int algo ); +int check_digest_algo( int algo ); MD_HANDLE md_open( int algo, int secure ); void md_enable( MD_HANDLE hd, int algo ); MD_HANDLE md_copy( MD_HANDLE a ); diff --git a/cipher/misc.c b/cipher/misc.c deleted file mode 100644 index b81a4fa4b..000000000 --- a/cipher/misc.c +++ /dev/null @@ -1,175 +0,0 @@ -/* misc.c - utility functions - * 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 - */ - -#include -#include -#include -#include -#include -#include "util.h" -#include "cipher.h" - - -static struct { const char *name; int algo;} pubkey_names[] = { - { "RSA", PUBKEY_ALGO_RSA }, - { "RSA-E", PUBKEY_ALGO_RSA_E }, - { "RSA-S", PUBKEY_ALGO_RSA_S }, - { "ELG", PUBKEY_ALGO_ELGAMAL }, - { "ELG-E", PUBKEY_ALGO_ELGAMAL_E }, - { "ELGAMAL", PUBKEY_ALGO_ELGAMAL }, - { "DSA", PUBKEY_ALGO_DSA }, - {NULL} }; - -/* Note: the first string is the one used by ascii armor */ -static struct { const char *name; int algo;} digest_names[] = { - { "MD5", DIGEST_ALGO_MD5 }, - { "SHA1", DIGEST_ALGO_SHA1 }, - { "SHA-1", DIGEST_ALGO_SHA1 }, - { "RIPEMD160", DIGEST_ALGO_RMD160 }, - { "RMD160", DIGEST_ALGO_RMD160 }, - { "RMD-160", DIGEST_ALGO_RMD160 }, - { "RIPE-MD-160", DIGEST_ALGO_RMD160 }, - { "TIGER", DIGEST_ALGO_TIGER }, - {NULL} }; - - - - - -/**************** - * Map a string to the pubkey algo - */ -int -string_to_pubkey_algo( const char *string ) -{ - int i; - const char *s; - - for(i=0; (s=pubkey_names[i].name); i++ ) - if( !stricmp( s, string ) ) - return pubkey_names[i].algo; - return 0; -} - - -/**************** - * Map a pubkey algo to a string - */ -const char * -pubkey_algo_to_string( int algo ) -{ - int i; - - if( is_ELGAMAL(algo) ) - algo = PUBKEY_ALGO_ELGAMAL; - else if( is_RSA(algo) ) - algo = PUBKEY_ALGO_RSA; - - for(i=0; pubkey_names[i].name; i++ ) - if( pubkey_names[i].algo == algo ) - return pubkey_names[i].name; - return NULL; -} - - - -/**************** - * Map a string to the digest algo - */ -int -string_to_digest_algo( const char *string ) -{ - int i; - const char *s; - - for(i=0; (s=digest_names[i].name); i++ ) - if( !stricmp( s, string ) ) - return digest_names[i].algo; - return 0; -} - - -/**************** - * Map a digest algo to a string - */ -const char * -digest_algo_to_string( int algo ) -{ - int i; - - for(i=0; digest_names[i].name; i++ ) - if( digest_names[i].algo == algo ) - return digest_names[i].name; - return NULL; -} - - - - -int -check_pubkey_algo( int algo ) -{ - return check_pubkey_algo2( algo, 0 ); -} - -/**************** - * a usage of 0 means: don't care - */ -int -check_pubkey_algo2( int algo, unsigned usage ) -{ - switch( algo ) { - case PUBKEY_ALGO_DSA: - if( usage & 2 ) - return G10ERR_WR_PUBKEY_ALGO; - return 0; - - case PUBKEY_ALGO_ELGAMAL: - case PUBKEY_ALGO_ELGAMAL_E: - return 0; - - #ifdef HAVE_RSA_CIPHER - case PUBKEY_ALGO_RSA: - return 0; - #endif - default: - return G10ERR_PUBKEY_ALGO; - } -} - - -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: - return 0; - default: - return G10ERR_DIGEST_ALGO; - } -} - - - diff --git a/cipher/primegen.c b/cipher/primegen.c index 26d21acb9..23aa1dbe8 100644 --- a/cipher/primegen.c +++ b/cipher/primegen.c @@ -112,6 +112,8 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits, /* make a pool of 3n+5 primes (this is an arbitrary value) */ m = n*3+5; + if( mode == 1 ) + m += 5; /* need some more for DSA */ if( m < 25 ) m = 25; pool = m_alloc_clear( m * sizeof *pool ); diff --git a/cipher/pubkey.c b/cipher/pubkey.c index 0a4b3430d..3357ae12c 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -30,18 +30,282 @@ #include "cipher.h" #include "dynload.h" + +#define TABLE_SIZE 20 + +struct pubkey_table_s { + const char *name; + int algo; + int npkey; + int nskey; + int nenc; + int nsig; + int usage; + int (*generate)( int algo, unsigned nbits, MPI *skey, MPI **retfactors ); + int (*check_secret_key)( int algo, MPI *skey ); + 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 ); + unsigned (*get_nbits)( int algo, MPI *pkey ); +}; + +static struct pubkey_table_s pubkey_table[TABLE_SIZE]; + + + +static int +dummy_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ) +{ log_bug("no generate() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } + +static int +dummy_check_secret_key( int algo, MPI *skey ) +{ log_bug("no check_secret_key() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } + +static int +dummy_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) +{ log_bug("no encrypt() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } + +static int +dummy_decrypt( int algo, MPI *result, MPI *data, MPI *skey ) +{ log_bug("no decrypt() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } + +static int +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 ) +{ log_bug("no verify() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } + +static unsigned +dummy_get_nbits( int algo, MPI *pkey ) +{ log_bug("no get_nbits() for %d\n", algo ); return 0; } + + +/**************** + * Put the static entries into the table. + */ +static void +setup_pubkey_table() +{ + + static int initialized = 0; + int i; + + if( initialized ) + return; + + i = 0; + pubkey_table[i].algo = PUBKEY_ALGO_ELGAMAL; + pubkey_table[i].name = elg_get_info( pubkey_table[i].algo, + &pubkey_table[i].npkey, + &pubkey_table[i].nskey, + &pubkey_table[i].nenc, + &pubkey_table[i].nsig, + &pubkey_table[i].usage ); + pubkey_table[i].generate = elg_generate; + pubkey_table[i].check_secret_key = elg_check_secret_key; + pubkey_table[i].encrypt = elg_encrypt; + pubkey_table[i].decrypt = elg_decrypt; + pubkey_table[i].sign = elg_sign; + pubkey_table[i].verify = elg_verify; + pubkey_table[i].get_nbits = elg_get_nbits; + if( !pubkey_table[i].name ) + BUG(); + i++; + pubkey_table[i].algo = PUBKEY_ALGO_ELGAMAL_E; + pubkey_table[i].name = elg_get_info( pubkey_table[i].algo, + &pubkey_table[i].npkey, + &pubkey_table[i].nskey, + &pubkey_table[i].nenc, + &pubkey_table[i].nsig, + &pubkey_table[i].usage ); + pubkey_table[i].generate = elg_generate; + pubkey_table[i].check_secret_key = elg_check_secret_key; + pubkey_table[i].encrypt = elg_encrypt; + pubkey_table[i].decrypt = elg_decrypt; + pubkey_table[i].sign = elg_sign; + pubkey_table[i].verify = elg_verify; + pubkey_table[i].get_nbits = elg_get_nbits; + if( !pubkey_table[i].name ) + BUG(); + i++; + pubkey_table[i].algo = PUBKEY_ALGO_DSA; + pubkey_table[i].name = dsa_get_info( pubkey_table[i].algo, + &pubkey_table[i].npkey, + &pubkey_table[i].nskey, + &pubkey_table[i].nenc, + &pubkey_table[i].nsig, + &pubkey_table[i].usage ); + pubkey_table[i].generate = dsa_generate; + pubkey_table[i].check_secret_key = dsa_check_secret_key; + pubkey_table[i].encrypt = dummy_encrypt; + pubkey_table[i].decrypt = dummy_decrypt; + pubkey_table[i].sign = dsa_sign; + pubkey_table[i].verify = dsa_verify; + pubkey_table[i].get_nbits = dsa_get_nbits; + if( !pubkey_table[i].name ) + BUG(); + i++; + + for( ; i < TABLE_SIZE; i++ ) + pubkey_table[i].name = NULL; + initialized = 1; +} + + +/**************** + * Try to load all modules and return true if new modules are available + */ +static int +load_pubkey_modules() +{ + static int done = 0; + void *context = NULL; + struct pubkey_table_s *ct; + int ct_idx; + int i; + const char *name; + int any = 0; + + if( done ) + return 0; + done = 1; + for(ct_idx=0, ct = pubkey_table; ct_idx < TABLE_SIZE; ct_idx++,ct++ ) { + if( !ct->name ) + break; + } + if( ct_idx >= TABLE_SIZE-1 ) + BUG(); /* table already full */ + /* now load all extensions */ + while( (name = enum_gnupgext_pubkeys( &context, &ct->algo, + &ct->npkey, &ct->nskey, &ct->nenc, + &ct->nsig, &ct->usage, + &ct->generate, + &ct->check_secret_key, + &ct->encrypt, + &ct->decrypt, + &ct->sign, + &ct->verify, + &ct->get_nbits )) ) { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == ct->algo ) + break; + if( pubkey_table[i].name ) { + log_info("skipping pubkey %d: already loaded\n", ct->algo ); + continue; + } + + if( !ct->generate ) ct->generate = dummy_generate; + if( !ct->check_secret_key ) ct->check_secret_key = + dummy_check_secret_key; + if( !ct->encrypt ) ct->encrypt = dummy_encrypt; + if( !ct->decrypt ) ct->decrypt = dummy_decrypt; + if( !ct->sign ) ct->sign = dummy_sign; + if( !ct->verify ) ct->verify = dummy_verify; + if( !ct->get_nbits ) ct->get_nbits= dummy_get_nbits; + /* put it into the table */ + if( g10_opt_verbose > 1 ) + log_info("loaded pubkey %d (%s)\n", ct->algo, name); + ct->name = name; + ct_idx++; + ct++; + any = 1; + /* check whether there are more available table slots */ + if( ct_idx >= TABLE_SIZE-1 ) { + log_info("pubkey table full; ignoring other extensions\n"); + break; + } + } + enum_gnupgext_pubkeys( &context, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL ); + return any; +} + + +/**************** + * Map a string to the pubkey algo + */ +int +string_to_pubkey_algo( const char *string ) +{ + int i; + const char *s; + + setup_pubkey_table(); + do { + for(i=0; (s=pubkey_table[i].name); i++ ) + if( !stricmp( s, string ) ) + return pubkey_table[i].algo; + } while( load_pubkey_modules() ); + return 0; +} + + +/**************** + * Map a pubkey algo to a string + */ +const char * +pubkey_algo_to_string( int algo ) +{ + int i; + + setup_pubkey_table(); + do { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == algo ) + return pubkey_table[i].name; + } while( load_pubkey_modules() ); + return NULL; +} + + + +int +check_pubkey_algo( int algo ) +{ + return check_pubkey_algo2( algo, 0 ); +} + +/**************** + * a usage of 0 means: don't care + */ +int +check_pubkey_algo2( int algo, unsigned usage ) +{ + int i; + + setup_pubkey_table(); + do { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == algo ) { + if( (usage & 1) && !(pubkey_table[i].usage & 1) ) + return G10ERR_WR_PUBKEY_ALGO; + if( (usage & 2) && !(pubkey_table[i].usage & 2) ) + return G10ERR_WR_PUBKEY_ALGO; + return 0; /* okay */ + } + } while( load_pubkey_modules() ); + return G10ERR_PUBKEY_ALGO; +} + + + + /**************** * Return the number of public key material numbers */ int pubkey_get_npkey( int algo ) { - if( is_ELGAMAL(algo) ) - return 3; - if( is_RSA(algo) ) - return 2; - if( algo == PUBKEY_ALGO_DSA ) - return 4; + int i; + setup_pubkey_table(); + do { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == algo ) + return pubkey_table[i].npkey; + } while( load_pubkey_modules() ); return 0; } @@ -51,12 +315,13 @@ pubkey_get_npkey( int algo ) int pubkey_get_nskey( int algo ) { - if( is_ELGAMAL(algo) ) - return 4; - if( is_RSA(algo) ) - return 6; - if( algo == PUBKEY_ALGO_DSA ) - return 5; + int i; + setup_pubkey_table(); + do { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == algo ) + return pubkey_table[i].nskey; + } while( load_pubkey_modules() ); return 0; } @@ -66,12 +331,13 @@ pubkey_get_nskey( int algo ) int pubkey_get_nsig( int algo ) { - if( is_ELGAMAL(algo) ) - return 2; - if( is_RSA(algo) ) - return 1; - if( algo == PUBKEY_ALGO_DSA ) - return 2; + int i; + setup_pubkey_table(); + do { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == algo ) + return pubkey_table[i].nsig; + } while( load_pubkey_modules() ); return 0; } @@ -81,10 +347,13 @@ pubkey_get_nsig( int algo ) int pubkey_get_nenc( int algo ) { - if( is_ELGAMAL(algo) ) - return 2; - if( is_RSA(algo) ) - return 1; + int i; + setup_pubkey_table(); + do { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == algo ) + return pubkey_table[i].nenc; + } while( load_pubkey_modules() ); return 0; } @@ -94,61 +363,46 @@ pubkey_get_nenc( int algo ) unsigned pubkey_nbits( int algo, MPI *pkey ) { - if( is_ELGAMAL( algo ) ) - return mpi_get_nbits( pkey[0] ); - - if( algo == PUBKEY_ALGO_DSA ) - return mpi_get_nbits( pkey[0] ); - - if( is_RSA( algo) ) - return mpi_get_nbits( pkey[0] ); + int i; + setup_pubkey_table(); + do { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == algo ) + return (*pubkey_table[i].get_nbits)( algo, pkey ); + } while( load_pubkey_modules() ); return 0; } +int +pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ) +{ + int i; + + setup_pubkey_table(); + do { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == algo ) + return (*pubkey_table[i].generate)( algo, nbits, + skey, retfactors ); + } while( load_pubkey_modules() ); + return G10ERR_PUBKEY_ALGO; +} + + int pubkey_check_secret_key( int algo, MPI *skey ) { - int rc = 0; + int i; - if( is_ELGAMAL(algo) ) { - ELG_secret_key sk; - sk.p = skey[0]; - sk.g = skey[1]; - sk.y = skey[2]; - sk.x = skey[3]; - if( !elg_check_secret_key( &sk ) ) - rc = G10ERR_BAD_SECKEY; - } - else if( algo == PUBKEY_ALGO_DSA ) { - DSA_secret_key sk; - sk.p = skey[0]; - sk.q = skey[1]; - sk.g = skey[2]; - sk.y = skey[3]; - sk.x = skey[4]; - if( !dsa_check_secret_key( &sk ) ) - rc = G10ERR_BAD_SECKEY; - } - #ifdef HAVE_RSA_CIPHER - else if( is_RSA(k->pubkey_algo) ) { - /* FIXME */ - RSA_secret_key sk; - assert( ndata == 1 && nskey == 6 ); - sk.n = skey[0]; - sk.e = skey[1]; - sk.d = skey[2]; - sk.p = skey[3]; - sk.q = skey[4]; - sk.u = skey[5]; - plain = mpi_alloc_secure( mpi_get_nlimbs(sk.n) ); - rsa_secret( plain, data[0], &sk ); - } - #endif - else - rc = G10ERR_PUBKEY_ALGO; - return rc; + setup_pubkey_table(); + do { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == algo ) + return (*pubkey_table[i].check_secret_key)( algo, skey ); + } while( load_pubkey_modules() ); + return G10ERR_PUBKEY_ALGO; } @@ -161,41 +415,32 @@ pubkey_check_secret_key( int algo, MPI *skey ) int pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) { + int i, rc; + + /* FIXME: check that data fits into the key (in xxx_encrypt)*/ + + setup_pubkey_table(); if( DBG_CIPHER ) { - int i; log_debug("pubkey_encrypt: algo=%d\n", algo ); for(i=0; i < pubkey_get_npkey(algo); i++ ) log_mpidump(" pkey:", pkey[i] ); log_mpidump(" data:", data ); } - /* FIXME: check that data fits into the key */ - if( is_ELGAMAL(algo) ) { - ELG_public_key pk; - pk.p = pkey[0]; - pk.g = pkey[1]; - pk.y = pkey[2]; - resarr[0] = mpi_alloc( mpi_get_nlimbs( pk.p ) ); - resarr[1] = mpi_alloc( mpi_get_nlimbs( pk.p ) ); - elg_encrypt( resarr[0], resarr[1], data, &pk ); - } - #ifdef HAVE_RSA_CIPHER - else if( algo == PUBKEY_ALGO_RSA || algo == PUBKEY_ALGO_RSA_E ) { - RSA_public_key pk; - pk.n = pkey[0]; - pk.e = pkey[1]; - resarr[0] = mpi_alloc( mpi_get_nlimbs( pk.p ) ); - rsa_public( resarr[0], data, &pk ); - } - #endif - else - return G10ERR_PUBKEY_ALGO; - if( DBG_CIPHER ) { - int i; + do { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == algo ) { + rc = (*pubkey_table[i].encrypt)( algo, resarr, data, pkey ); + goto ready; + } + } while( load_pubkey_modules() ); + rc = G10ERR_PUBKEY_ALGO; + ready: + if( !rc && DBG_CIPHER ) { for(i=0; i < pubkey_get_nenc(algo); i++ ) log_mpidump(" encr:", resarr[i] ); } - return 0; + return rc; } @@ -210,44 +455,31 @@ pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) int pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey ) { - MPI plain = NULL; + int i, rc; + setup_pubkey_table(); *result = NULL; /* so the caller can always do an mpi_free */ if( DBG_CIPHER ) { - int i; log_debug("pubkey_decrypt: algo=%d\n", algo ); for(i=0; i < pubkey_get_nskey(algo); i++ ) log_mpidump(" skey:", skey[i] ); for(i=0; i < pubkey_get_nenc(algo); i++ ) log_mpidump(" data:", data[i] ); } - if( is_ELGAMAL(algo) ) { - ELG_secret_key sk; - sk.p = skey[0]; - sk.g = skey[1]; - sk.y = skey[2]; - sk.x = skey[3]; - plain = mpi_alloc_secure( mpi_get_nlimbs( sk.p ) ); - elg_decrypt( plain, data[0], data[1], &sk ); - } - #ifdef HAVE_RSA_CIPHER - else if( algo == PUBKEY_ALGO_RSA || algo == PUBKEY_ALGO_RSA_E ) { - RSA_secret_key sk; - sk.n = skey[0]; - sk.e = skey[1]; - sk.d = skey[2]; - sk.p = skey[3]; - sk.q = skey[4]; - sk.u = skey[5]; - plain = mpi_alloc_secure( mpi_get_nlimbs(sk.n) ); - rsa_secret( plain, data[0], &sk ); - } - #endif - else - return G10ERR_PUBKEY_ALGO; - *result = plain; - return 0; + do { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == algo ) { + rc = (*pubkey_table[i].decrypt)( algo, result, data, skey ); + goto ready; + } + } while( load_pubkey_modules() ); + rc = G10ERR_PUBKEY_ALGO; + ready: + if( !rc && DBG_CIPHER ) { + log_mpidump(" plain:", *result ); + } + return rc; } @@ -260,58 +492,30 @@ pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey ) int pubkey_sign( int algo, MPI *resarr, MPI data, MPI *skey ) { + int i, rc; + + setup_pubkey_table(); if( DBG_CIPHER ) { - int i; log_debug("pubkey_sign: algo=%d\n", algo ); for(i=0; i < pubkey_get_nskey(algo); i++ ) log_mpidump(" skey:", skey[i] ); log_mpidump(" data:", data ); } - if( is_ELGAMAL(algo) ) { - ELG_secret_key sk; - sk.p = skey[0]; - sk.g = skey[1]; - sk.y = skey[2]; - sk.x = skey[3]; - resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); - resarr[1] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); - elg_sign( resarr[0], resarr[1], data, &sk ); - } - else if( algo == PUBKEY_ALGO_DSA ) { - DSA_secret_key sk; - sk.p = skey[0]; - sk.q = skey[1]; - sk.g = skey[2]; - sk.y = skey[3]; - sk.x = skey[4]; - resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); - resarr[1] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); - dsa_sign( resarr[0], resarr[1], data, &sk ); - } - #ifdef HAVE_RSA_CIPHER - else if( algo == PUBKEY_ALGO_RSA || algo == PUBKEY_ALGO_RSA_S ) { - RSA_secret_key sk; - sk.n = skey[0]; - sk.e = skey[1]; - sk.d = skey[2]; - sk.p = skey[3]; - sk.q = skey[4]; - sk.u = skey[5]; - plain = mpi_alloc_secure( mpi_get_nlimbs(sk.n) ); - rsa_sign( plain, data[0], &sk ); - } - #endif - else - return G10ERR_PUBKEY_ALGO; - - if( DBG_CIPHER ) { - int i; + do { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == algo ) { + rc = (*pubkey_table[i].sign)( algo, resarr, data, skey ); + goto ready; + } + } while( load_pubkey_modules() ); + rc = G10ERR_PUBKEY_ALGO; + ready: + if( !rc && DBG_CIPHER ) { for(i=0; i < pubkey_get_nsig(algo); i++ ) log_mpidump(" sig:", resarr[i] ); } - - return 0; + return rc; } /**************** @@ -321,113 +525,18 @@ pubkey_sign( int algo, MPI *resarr, MPI data, MPI *skey ) int pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey ) { - int rc = 0; + int i, rc; - if( is_ELGAMAL( algo ) ) { - ELG_public_key pk; - pk.p = pkey[0]; - pk.g = pkey[1]; - pk.y = pkey[2]; - if( !elg_verify( data[0], data[1], hash, &pk ) ) - rc = G10ERR_BAD_SIGN; - } - else if( algo == PUBKEY_ALGO_DSA ) { - DSA_public_key pk; - pk.p = pkey[0]; - pk.q = pkey[1]; - pk.g = pkey[2]; - pk.y = pkey[3]; - if( !dsa_verify( data[0], data[1], hash, &pk ) ) - rc = G10ERR_BAD_SIGN; - } - #ifdef HAVE_RSA_CIPHER - else if( algo == PUBKEY_ALGO_RSA || algo == PUBKEY_ALGO_RSA_S ) { - RSA_public_key pk; - int i, j, c, old_enc; - byte *dp; - const byte *asn; - size_t mdlen, asnlen; - - pk.e = pkey[0]; - pk.n = pkey[1]; - result = mpi_alloc(40); - rsa_public( result, data[0], &pk ); - - 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; + setup_pubkey_table(); + do { + for(i=0; pubkey_table[i].name; i++ ) + if( pubkey_table[i].algo == algo ) { + rc = (*pubkey_table[i].verify)( algo, hash, data, pkey ); + goto ready; } - 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; - } - - /* 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; - break; - } - } - } - #endif - else - rc = G10ERR_PUBKEY_ALGO; - + } while( load_pubkey_modules() ); + rc = G10ERR_PUBKEY_ALGO; + ready: return rc; } diff --git a/doc/DETAILS b/doc/DETAILS index 7ff8e2420..a9f04090f 100644 --- a/doc/DETAILS +++ b/doc/DETAILS @@ -103,7 +103,7 @@ Record type 3: and useful if we have duplicate keyids It points back to the directory node. 1 byte pubkey algorithm - 1 byte reserved + 1 byte length of the fingerprint (in bytes) 20 bytes fingerprint of the public key 1 byte ownertrust: 3 byte reserved diff --git a/g10/g10.c b/g10/g10.c index 94fb6446b..8f65f2efc 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -310,6 +310,11 @@ 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 ) @@ -317,9 +322,10 @@ 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; + } @@ -542,7 +548,8 @@ main( int argc, char **argv ) #endif /* IS_G10MAINT */ case 'o': opt.outfile = pargs.r.ret_str; break; - case 'v': opt.verbose++; opt.list_sigs=1; break; + case 'v': g10_opt_verbose++; + opt.verbose++; opt.list_sigs=1; break; case 'k': set_cmd( &cmd, aKMode ); break; case 500: opt.batch = 1; greeting = 0; break; @@ -567,7 +574,8 @@ main( int argc, char **argv ) case 520: default_keyring = 0; break; case 521: set_cmd( &cmd, aListPackets); break; case 522: greeting = 0; break; - case 526: opt.verbose = 0; opt.list_sigs=0; break; + case 526: g10_opt_verbose = 0; + opt.verbose = 0; opt.list_sigs=0; break; case 530: set_cmd( &cmd, aImport); break; case 532: quick_random_gen(1); break; case 534: opt.no_comment=1; break; @@ -633,6 +641,7 @@ main( int argc, char **argv ) opt.list_sigs++; opt.verbose = opt.verbose > 1; + g10_opt_verbose = opt.verbose; } diff --git a/g10/getkey.c b/g10/getkey.c index fb4a8492d..5f607ec51 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -474,16 +474,18 @@ get_pubkey_byname( PKT_public_cert *pkc, const char *name ) /**************** * Search for a key with the given fingerprint and return the * complete keyblock which may have more than only this key. - * The fingerprint should always be 20 bytes, fill with zeroes - * for 16 byte fprints. */ int -get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint ) +get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint, + size_t fprint_len ) { int rc; PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc ); - rc = lookup( pkc, 20, NULL, fprint, ret_keyblock ); + if( fprint_len == 20 || fprint_len == 16 ) + rc = lookup( pkc, fprint_len, NULL, fprint, ret_keyblock ); + else + rc = G10ERR_GENERAL; /* Oops */ free_public_cert( pkc ); return rc; diff --git a/g10/keydb.h b/g10/keydb.h index 1cd6457a3..07d9115b3 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -109,7 +109,8 @@ void add_secret_keyring( const char *name ); int get_pubkey( PKT_public_cert *pkc, u32 *keyid ); int get_pubkey_byname( PKT_public_cert *pkc, const char *name ); int get_seckey( PKT_secret_cert *skc, u32 *keyid ); -int get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint ); +int get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint, + size_t fprint_len ); int seckey_available( u32 *keyid ); int get_seckey_byname( PKT_secret_cert *skc, const char *name, int unlock ); int enum_secret_keys( void **context, PKT_secret_cert *skc ); diff --git a/g10/keygen.c b/g10/keygen.c index 63c162fb2..8ad30bb9b 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -35,7 +35,7 @@ #include "i18n.h" -#if defined(HAVE_RSA_CIPHER) && 0 +#if 0 #define ENABLE_RSA_KEYGEN 1 #endif @@ -143,11 +143,14 @@ gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, PACKET *pkt; PKT_secret_cert *skc; PKT_public_cert *pkc; - ELG_public_key pk; - ELG_secret_key sk; + MPI skey[4]; MPI *factors; - elg_generate( &pk, &sk, nbits, &factors ); + rc = pubkey_generate( PUBKEY_ALGO_ELGAMAL, nbits, skey, &factors ); + if( rc ) { + log_error("pubkey_generate failed: %s\n", g10_errstr(rc) ); + return rc; + } skc = m_alloc_clear( sizeof *skc ); pkc = m_alloc_clear( sizeof *pkc ); @@ -155,13 +158,13 @@ gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, skc->version = pkc->version = version; skc->valid_days = pkc->valid_days = valid_days; skc->pubkey_algo = pkc->pubkey_algo = PUBKEY_ALGO_ELGAMAL; - pkc->pkey[0] = pk.p; - pkc->pkey[1] = pk.g; - pkc->pkey[2] = pk.y; - skc->skey[0] = sk.p; - skc->skey[1] = sk.g; - skc->skey[2] = sk.y; - skc->skey[3] = sk.x; + pkc->pkey[0] = mpi_copy( skey[0] ); + pkc->pkey[1] = mpi_copy( skey[1] ); + pkc->pkey[2] = mpi_copy( skey[2] ); + skc->skey[0] = skey[0]; + skc->skey[1] = skey[1]; + skc->skey[2] = skey[2]; + skc->skey[3] = skey[3]; skc->is_protected = 0; skc->protect.algo = 0; @@ -278,14 +281,17 @@ gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, PACKET *pkt; PKT_secret_cert *skc; PKT_public_cert *pkc; - DSA_public_key pk; - DSA_secret_key sk; + MPI skey[5]; MPI *factors; if( nbits > 1024 ) nbits = 1024; - dsa_generate( &pk, &sk, nbits, &factors ); + rc = pubkey_generate( PUBKEY_ALGO_DSA, nbits, skey, &factors ); + if( rc ) { + log_error("pubkey_generate failed: %s\n", g10_errstr(rc) ); + return rc; + } skc = m_alloc_clear( sizeof *skc ); pkc = m_alloc_clear( sizeof *pkc ); @@ -296,15 +302,15 @@ gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, */ skc->valid_days = pkc->valid_days = valid_days; skc->pubkey_algo = pkc->pubkey_algo = PUBKEY_ALGO_DSA; - pkc->pkey[0] = pk.p; - pkc->pkey[1] = pk.q; - pkc->pkey[2] = pk.g; - pkc->pkey[3] = pk.y; - skc->skey[0] = sk.p; - skc->skey[1] = sk.q; - skc->skey[2] = sk.g; - skc->skey[3] = sk.y; - skc->skey[4] = sk.x; + pkc->pkey[0] = skey[0]; + pkc->pkey[1] = skey[1]; + pkc->pkey[2] = skey[2]; + pkc->pkey[3] = skey[3]; + skc->skey[0] = skey[0]; + skc->skey[1] = skey[1]; + skc->skey[2] = skey[2]; + skc->skey[3] = skey[3]; + skc->skey[4] = skey[4]; skc->is_protected = 0; skc->protect.algo = 0; diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 0ee6e7d37..0cd4238ad 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -972,15 +972,15 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen, } else { - if( list_mode ) - printf( "\tprotect algo: %d\n", - cert->protect.algo); /* old version, we don't have a S2K, so we fake one */ cert->protect.s2k.mode = 0; /* We need this kludge to cope with old GNUPG versions */ cert->protect.s2k.hash_algo = cert->protect.algo == CIPHER_ALGO_BLOWFISH160? DIGEST_ALGO_RMD160 : DIGEST_ALGO_MD5; + if( list_mode ) + printf( "\tprotect algo: %d (hash algo: %d)\n", + cert->protect.algo, cert->protect.s2k.hash_algo ); } if( pktlen < 8 ) { rc = G10ERR_INVALID_PACKET; @@ -1176,6 +1176,9 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen, } if( cert->protect.algo == CIPHER_ALGO_BLOWFISH160 ) 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; } else cert->is_protected = 0; diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index 41a09b281..9ac19c89c 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -81,27 +81,25 @@ do_check( PKT_secret_cert *cert ) csum = checksum_mpi( cert->skey[4] ); m_free( buffer ); break; - #ifdef HAVE_RSA_CIPHER 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->d.rsa.##a, \ + 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->d.rsa.##a, buffer, nbytes, 0 ); \ + mpi_set_buffer(cert->skey[(a)], buffer, nbytes, 0 ); \ m_free( buffer ); \ } while(0) - X(d); - X(p); - X(q); - X(u); + X(2); + X(3); + X(4); + X(5); #undef X break; - #endif /* HAVE_RSA_CIPHER */ default: BUG(); } @@ -135,29 +133,27 @@ do_check( PKT_secret_cert *cert ) case PUBKEY_ALGO_DSA: csum = checksum_mpi( cert->skey[4] ); break; - #ifdef HAVE_RSA_CIPHER case PUBKEY_ALGO_RSA_E: case PUBKEY_ALGO_RSA_S: case PUBKEY_ALGO_RSA: csum =0; - buffer = mpi_get_buffer( cert->d.rsa.rsa_d, &nbytes, NULL ); + 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->d.rsa.rsa_p, &nbytes, NULL ); + 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->d.rsa.rsa_q, &nbytes, NULL ); + 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->d.rsa.rsa_u, &nbytes, NULL ); + buffer = mpi_get_buffer( cert->skey[5], &nbytes, NULL ); csum += checksum_u16( nbytes*8 ); csum += checksum( buffer, nbytes ); m_free( buffer ); break; - #endif default: BUG(); } if( csum != cert->csum ) @@ -182,36 +178,22 @@ check_secret_key( PKT_secret_cert *cert ) for(i=0; i < 3 && rc == G10ERR_BAD_PASS; i++ ) { if( i ) log_error(_("Invalid passphrase; please try again ...\n")); - switch( cert->pubkey_algo ) { - case PUBKEY_ALGO_ELGAMAL_E: - case PUBKEY_ALGO_ELGAMAL: - case PUBKEY_ALGO_DSA: + rc = do_check( cert ); + #if 0 /* set to 1 to enable the workaround */ + if( rc == G10ERR_BAD_PASS && cert->is_protected + && cert->protect.algo == CIPHER_ALGO_BLOWFISH + && cert->pubkey_algo != PUBKEY_ALGO_ELGAMAL ) { + /* Workaround for a bug in 0.2.16 which still used + * a 160 bit key for BLOWFISH. */ + log_info("trying workaround for 0.2.16 passphrase bug ...\n"); + log_info("If you don't need this, uncomment it in g10/seckey-cert.c\n\n"); + cert->protect.algo = CIPHER_ALGO_BLOWFISH160; rc = do_check( cert ); - #if 0 /* set to 1 to enable the workaround */ - if( rc == G10ERR_BAD_PASS && cert->is_protected - && cert->protect.algo == CIPHER_ALGO_BLOWFISH - && cert->pubkey_algo != PUBKEY_ALGO_ELGAMAL ) { - /* Workaround for a bug in 0.2.16 which still used - * a 160 bit key for BLOWFISH. */ - log_info("trying workaround for 0.2.16 passphrase bug ...\n"); - log_info("If you don't need this, uncomment it in g10/seckey-cert.c\n\n"); - cert->protect.algo = CIPHER_ALGO_BLOWFISH160; - rc = do_check( cert ); - if( rc ) - rc = G10ERR_BAD_PASS; - cert->protect.algo = CIPHER_ALGO_BLOWFISH; - } - #endif - break; - #ifdef HAVE_RSA_CIPHER - case PUBKEY_ALGO_RSA: - case PUBKEY_ALGO_RSA_E: - case PUBKEY_ALGO_RSA_S: - rc = do_check( cert ); - break; - #endif - default: rc = G10ERR_PUBKEY_ALGO; + if( rc ) + rc = G10ERR_BAD_PASS; + cert->protect.algo = CIPHER_ALGO_BLOWFISH; } + #endif if( get_passphrase_fd() != -1 ) break; } diff --git a/g10/sig-check.c b/g10/sig-check.c index a4c802c67..0ef69b7d5 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -49,10 +49,8 @@ signature_check( PKT_signature *sig, MD_HANDLE digest ) int rc=0; - #ifndef HAVE_RSA_CIPHER if( is_RSA(sig->pubkey_algo) ) write_status(STATUS_RSA_OR_IDEA); - #endif if( get_pubkey( pkc, sig->keyid ) ) rc = G10ERR_NO_PUBKEY; @@ -149,7 +147,7 @@ do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest ) log_mpidump("calc sig frame: ", result); rc = pubkey_verify( pkc->pubkey_algo, result, sig->data, pkc->pkey ); } - #ifdef HAVE_RSA_CIPHER + #if 0 /* WORK!!! */ else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA || pkc->pubkey_algo == PUBKEY_ALGO_RSA_S ) { int i, j, c, old_enc; @@ -231,7 +229,7 @@ do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest ) } } } - #endif/*HAVE_RSA_CIPHER*/ + #endif else { /*log_debug("signature_check: unsupported pubkey algo %d\n", pkc->pubkey_algo );*/ diff --git a/g10/trustdb.c b/g10/trustdb.c index 3ebc83137..bb4942c41 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -83,6 +83,7 @@ struct trust_record { ulong owner; u32 keyid[2]; byte pubkey_algo; + byte fingerprint_len; byte fingerprint[20]; byte ownertrust; } key; @@ -387,9 +388,11 @@ dump_record( ulong rnum, TRUSTREC *rec, FILE *fp ) fputs(", (??)", fp ); putc('\n', fp); break; - case RECTYPE_KEY: fprintf(fp, "key keyid=%08lX, own=%lu, ownertrust=%02x\n", + case RECTYPE_KEY: fprintf(fp, + "key keyid=%08lX, own=%lu, ownertrust=%02x, fl=%d\n", (ulong)rec->r.key.keyid[1], - rec->r.key.owner, rec->r.key.ownertrust ); + rec->r.key.owner, rec->r.key.ownertrust, + rec->r.key.fingerprint_len ); break; case RECTYPE_CTL: fprintf(fp, "ctl\n"); break; @@ -497,7 +500,10 @@ read_record( ulong recnum, TRUSTREC *rec, int expected ) rec->r.key.owner = buftoulong(p); p += 4; rec->r.dir.keyid[0] = buftou32(p); p += 4; rec->r.dir.keyid[1] = buftou32(p); p += 4; - rec->r.key.pubkey_algo = *p++; p++; + rec->r.key.pubkey_algo = *p++; + rec->r.key.fingerprint_len = *p++; + if( rec->r.key.fingerprint_len < 1 || rec->r.key.fingerprint_len > 20 ) + rec->r.key.fingerprint_len = 20; memcpy( rec->r.key.fingerprint, p, 20); p += 20; rec->r.key.ownertrust = *p++; break; @@ -562,7 +568,8 @@ write_record( ulong recnum, TRUSTREC *rec ) ulongtobuf(p, rec->r.key.owner); p += 4; u32tobuf(p, rec->r.key.keyid[0]); p += 4; u32tobuf(p, rec->r.key.keyid[1]); p += 4; - *p++ = rec->r.key.pubkey_algo; p++; + *p++ = rec->r.key.pubkey_algo; + *p++ = rec->r.key.fingerprint_len; memcpy( p, rec->r.key.fingerprint, 20); p += 20; *p++ = rec->r.key.ownertrust; break; @@ -1166,7 +1173,8 @@ build_sigrecs( ulong pubkeyid ) log_error(_("%lu: build_sigrecs: can't read key record\n"), pubkeyid); goto leave; } - rc = get_keyblock_byfprint( &keyblock, krec.r.key.fingerprint ); + rc = get_keyblock_byfprint( &keyblock, krec.r.key.fingerprint, + krec.r.key.fingerprint_len ); if( rc ) { log_error(_("build_sigrecs: get_keyblock_byfprint failed\n") ); goto leave; @@ -1938,6 +1946,7 @@ insert_trust_record( PKT_public_cert *pkc ) rec.r.key.keyid[0] = keyid[0]; rec.r.key.keyid[1] = keyid[1]; rec.r.key.pubkey_algo = pkc->pubkey_algo; + rec.r.key.fingerprint_len = fingerlen; memcpy(rec.r.key.fingerprint, fingerprint, fingerlen ); rec.r.key.ownertrust = 0; if( write_record( knum, &rec ) ) { diff --git a/include/ChangeLog b/include/ChangeLog index 05b40fa04..0df9e6836 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +Sat Jun 13 17:31:32 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10lib.h: New as interface for the g10lib. + Mon Jun 8 22:14:48 1998 Werner Koch (wk@isil.d.shuttle.de) * cipher.h (CIPHER_ALGO_CAST5): Changed name from .. CAST diff --git a/include/cipher.h b/include/cipher.h index 3fe56c2e3..7913e4a33 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -25,7 +25,7 @@ #ifndef G10_CIPHER_H #define G10_CIPHER_H -#define DBG_CIPHER cipher_debug_mode +#define DBG_CIPHER g10c_debug_mode #include "mpi.h" #include "../cipher/md.h" @@ -84,9 +84,8 @@ struct cipher_handle_s { char does_not_matter[1]; }; #define CIPHER_MODE_DUMMY 5 /* used with algo DUMMY for no encryption */ - - -int cipher_debug_mode; +int g10c_debug_mode; +int g10_opt_verbose; /*-- dynload.c --*/ void register_cipher_extension( const char *fname ); @@ -110,27 +109,22 @@ void cipher_sync( CIPHER_HANDLE c ); #define PUBKEY_MAX_NSIG 2 #define PUBKEY_MAX_NENC 2 +int string_to_pubkey_algo( const char *string ); +const char * pubkey_algo_to_string( int algo ); +int check_pubkey_algo( int algo ); +int check_pubkey_algo2( int algo, unsigned usage ); int pubkey_get_npkey( int algo ); int pubkey_get_nskey( int algo ); int pubkey_get_nsig( int algo ); int pubkey_get_nenc( int algo ); unsigned pubkey_nbits( int algo, MPI *pkey ); +int pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ); 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 ); - -/*-- misc.c --*/ -int string_to_pubkey_algo( const char *string ); -int string_to_digest_algo( const char *string ); -const char * pubkey_algo_to_string( int algo ); -const char * digest_algo_to_string( int algo ); -int check_pubkey_algo( int algo ); -int check_pubkey_algo2( int algo, unsigned usage ); -int check_digest_algo( int algo ); - /*-- smallprime.c --*/ extern ushort small_prime_numbers[]; diff --git a/include/distfiles b/include/distfiles index 35ca3220b..6257e96ed 100644 --- a/include/distfiles +++ b/include/distfiles @@ -8,4 +8,6 @@ types.h util.h i18n.h +g10lib.h + ChangeLog diff --git a/include/g10lib.h b/include/g10lib.h new file mode 100644 index 000000000..12e846ca8 --- /dev/null +++ b/include/g10lib.h @@ -0,0 +1,174 @@ +/* g10lib.h - GNU digital encryption libray interface + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * FIXME: This should allow XFree programs etc to use the header. + */ + +#ifndef _g10lib_G10LIB_H +#define _g10lib_G10LIB_H +#ifdef __cplusplus +extern "C" { +#endif + + + +#ifndef _g10lib_INTERNAL +struct g10mpi_struct { int hidden_stuff; }; +typedef struct g10mpi_struct *MPI; +#endif + +int g10c_debug_mode; +int g10_opt_verbose; + +/******************************** + ******* math functions ******* + ********************************/ +MPI g10m_new( unsigned nbits ); +MPI g10m_new_secure( unsigned nbits ); +void g10m_release( MPI a ); +void g10m_resize( MPI a, unsigned nbits ); +MPI g10m_copy( MPI a ); +void g10m_swap( MPI a, MPI b); +void g10m_set( MPI w, MPI u); +void g10m_set_ui( MPI w, unsigned long u); +void g10m_set_bytes( MPI a, unsigned nbits, unsigned char (*fnc)(int), int opaque ); +int g10m_cmp( MPI u, MPI v ); +int g10m_cmp_ui( MPI u, unsigned long v ); + + +void g10m_add(MPI w, MPI u, MPI v); +void g10m_add_ui(MPI w, MPI u, unsigned long v ); +void g10m_sub( MPI w, MPI u, MPI v); +void g10m_sub_ui(MPI w, MPI u, unsigned long v ); + +void g10m_mul_ui(MPI w, MPI u, unsigned long v ); +void g10m_mul_2exp( MPI w, MPI u, unsigned long cnt); +void g10m_mul( MPI w, MPI u, MPI v); +void g10m_mulm( MPI w, MPI u, MPI v, MPI m); + +void g10m_fdiv_q( MPI quot, MPI dividend, MPI divisor ); + +void g10m_powm( MPI res, MPI base, MPI exp, MPI mod); + +int g10m_gcd( MPI g, MPI a, MPI b ); +int g10m_invm( MPI x, MPI u, MPI v ); + +unsigned g10m_get_nbits( MPI a ); +unsigned g10m_get_size( MPI a ); + + +/******************************************** + ******* symmetric cipher functions ******* + ********************************************/ + + + +/********************************************* + ******* asymmetric cipher functions ******* + *********************************************/ + + + + +/********************************************* + ******* cryptograhic hash functions ******* + *********************************************/ + + +/***************************************** + ******* miscellaneous functions ******* + *****************************************/ + +MPI g10c_generate_secret_prime( unsigned nbits ); +unsigned char g10c_get_random_byte( int level ); + + +void *g10_malloc( size_t n ); +void *g10_calloc( size_t n ); +void *g10_malloc_secure( size_t n ); +void *g10_calloc_secure( size_t n ); +void *g10_realloc( void *a, size_t n ); +void g10_free( void *p ); +char *g10_strdup( const char * a); + +void g10_log_bug( const char *fmt, ... ); +void g10_log_bug0( const char *, int ); +void g10_log_fatal( const char *fmt, ... ); +void g10_log_error( const char *fmt, ... ); +void g10_log_info( const char *fmt, ... ); +void g10_log_debug( const char *fmt, ... ); +void g10_log_hexdump( const char *text, char *buf, size_t len ); +void g10_log_mpidump( const char *text, MPI a ); + + +/*************************** + ******* constants ******* + **************************/ +#define CIPHER_ALGO_NONE 0 +#define CIPHER_ALGO_IDEA 1 +#define CIPHER_ALGO_3DES 2 +#define CIPHER_ALGO_CAST5 3 +#define CIPHER_ALGO_BLOWFISH 4 /* blowfish 128 bit key */ +#define CIPHER_ALGO_SAFER_SK128 5 +#define CIPHER_ALGO_DES_SK 6 +#define CIPHER_ALGO_BLOWFISH160 42 /* blowfish 160 bit key (not in OpenPGP)*/ +#define CIPHER_ALGO_DUMMY 110 /* no encryption at all */ + +#define PUBKEY_ALGO_RSA 1 +#define PUBKEY_ALGO_RSA_E 2 /* RSA encrypt only */ +#define PUBKEY_ALGO_RSA_S 3 /* RSA sign only */ +#define PUBKEY_ALGO_ELGAMAL_E 16 /* encrypt only ElGamal (but not vor v3)*/ +#define PUBKEY_ALGO_DSA 17 +#define PUBKEY_ALGO_ELGAMAL 20 /* sign and encrypt elgamal */ + +#define DIGEST_ALGO_MD5 1 +#define DIGEST_ALGO_SHA1 2 +#define DIGEST_ALGO_RMD160 3 +#define DIGEST_ALGO_TIGER 6 + +#define is_RSA(a) ((a)==PUBKEY_ALGO_RSA || (a)==PUBKEY_ALGO_RSA_E \ + || (a)==PUBKEY_ALGO_RSA_S ) +#define is_ELGAMAL(a) ((a)==PUBKEY_ALGO_ELGAMAL || (a)==PUBKEY_ALGO_ELGAMAL_E) + +#define G10ERR_GENERAL 1 +#define G10ERR_PUBKEY_ALGO 4 +#define G10ERR_DIGEST_ALGO 5 +#define G10ERR_BAD_PUBKEY 6 +#define G10ERR_BAD_SECKEY 7 +#define G10ERR_BAD_SIGN 8 +#define G10ERR_CIPHER_ALGO 12 +#define G10ERR_WRONG_SECKEY 18 +#define G10ERR_UNSUPPORTED 19 +#define G10ERR_NI_PUBKEY 27 +#define G10ERR_NI_CIPHER 28 +#define G10ERR_BAD_MPI 30 +#define G10ERR_WR_PUBKEY_ALGO 41 + + +/*********************************** + ******* some handy macros ******* + ***********************************/ + +#ifndef BUG + #define BUG() g10_log_bug0( __FILE__ , __LINE__ ) +#endif + +#ifndef STR + #define STR(v) #v + #define STR2(v) STR(v) +#endif + +#ifndef DIM + #define DIM(v) (sizeof(v)/sizeof((v)[0])) + #define DIMof(type,member) DIM(((type *)0)->member) +#endif + + +#define DBG_CIPHER g10c_debug_mode +#define OPT_VERBOSE g10_opt_verbose + + +#ifdef __cplusplus +} +#endif +#endif /* _g10lib_G10LIB_H */ diff --git a/mpi/Makefile.am b/mpi/Makefile.am index ead60a683..11a18bf54 100644 --- a/mpi/Makefile.am +++ b/mpi/Makefile.am @@ -34,7 +34,8 @@ libmpi_a_SOURCES = longlong.h \ mpih-sub.c \ mpih-div.c \ mpih-mul.c \ - mpiutil.c + mpiutil.c \ + g10m.c # Note this objects are actually links, the sourcefiles are # distributed by special code in dist-hook diff --git a/mpi/g10m.c b/mpi/g10m.c new file mode 100644 index 000000000..79d571462 --- /dev/null +++ b/mpi/g10m.c @@ -0,0 +1,90 @@ +/* g10m.c - Wrapper for MPI + * 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 + */ + +#include +#include +#include +#include "mpi.h" +#define _g10lib_INTERNAL 1 +#include "g10lib.h" + +MPI +g10m_new( unsigned nbits ) +{ + return mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB ); +} + +MPI +g10m_new_secure( unsigned nbits ) +{ + return mpi_alloc_secure( (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB ); +} + +void +g10m_release( MPI a ) +{ + mpi_free(a); +} + +void +g10m_resize( MPI a, unsigned nbits ) +{ + return mpi_resize( a, (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB ); +} + +MPI g10m_copy( MPI a ) { return mpi_copy( a ); } +void g10m_swap( MPI a, MPI b) { mpi_swap( a, b ); } +void g10m_set( MPI w, MPI u) { mpi_set( w, u ); } +void g10m_set_ui( MPI w, ulong u ) { mpi_set_ui( w, u ); } + +void +g10m_set_bytes( MPI a, unsigned nbits, byte (*fnc)(int), int opaque ) +{ + mpi_set_bytes( a, nbits, fnc, opaque ); +} + +int g10m_cmp( MPI u, MPI v ) { return mpi_cmp( u, v ); } +int g10m_cmp_ui( MPI u, ulong v ) { return mpi_cmp_ui( u, v ); } + +void g10m_add(MPI w, MPI u, MPI v) { mpi_add( w, u, v ); } +void g10m_add_ui(MPI w, MPI u, ulong v ) { mpi_add_ui( w, u, v ); } +void g10m_sub( MPI w, MPI u, MPI v) { mpi_sub( w, u, v ); } +void g10m_sub_ui(MPI w, MPI u, ulong v ) { mpi_sub_ui( w, u, v ); } + +void g10m_mul( MPI w, MPI u, MPI v) { mpi_mul( w, u, v ); } +void g10m_mulm( MPI w, MPI u, MPI v, MPI m) { mpi_mulm( w, u, v, m ); } +void g10m_mul_2exp( MPI w, MPI u, ulong cnt) { mpi_mul_2exp( w, u, cnt ); } +void g10m_mul_ui(MPI w, MPI u, ulong v ) { mpi_mul_ui( w, u, v ); } + +void g10m_fdiv_q( MPI q, MPI d, MPI r ) { mpi_fdiv_q( q, d, r ); } + +void g10m_powm( MPI r, MPI b, MPI e, MPI m) { mpi_powm( r, b, e, m ); } + +int g10m_gcd( MPI g, MPI a, MPI b ) { return mpi_gcd( g, a, b ); } +int g10m_invm( MPI x, MPI u, MPI v ) { mpi_invm( x, u, v ); return 0; } + +unsigned g10m_get_nbits( MPI a ) { return mpi_get_nbits( a ); } + +unsigned +g10m_get_size( MPI a ) +{ + return mpi_get_nlimbs( a ) * BITS_PER_MPI_LIMB; +} + diff --git a/util/Makefile.am b/util/Makefile.am index df60fbb64..baef6045a 100644 --- a/util/Makefile.am +++ b/util/Makefile.am @@ -5,7 +5,7 @@ INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl -I../intl noinst_LIBRARIES = libutil.a -libutil_a_SOURCES = logger.c fileutil.c miscutil.c strgutil.c \ +libutil_a_SOURCES = g10u.c logger.c fileutil.c miscutil.c strgutil.c \ ttyio.c argparse.c memory.c secmem.c errors.c iobuf.c diff --git a/util/g10u.c b/util/g10u.c new file mode 100644 index 000000000..1b0bc9d4c --- /dev/null +++ b/util/g10u.c @@ -0,0 +1,35 @@ +/* g10u.c - Wrapper for utility functions + * 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 + */ + +#include +#include +#include +#include "mpi.h" +#define _g10lib_INTERNAL 1 +#include "g10lib.h" + +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 ); } +void *g10_calloc_secure( size_t n ) { return m_alloc_secure_clear( n ); } +void *g10_realloc( void *a, size_t n ) { return m_realloc( a, n ); } +void g10_free( void *p ) { return m_free( p ); } +char *g10_strdup( const char * a) { return m_strdup( a ); } +