gnupg extension are now working
authorWerner Koch <wk@gnupg.org>
Sat, 13 Jun 1998 17:00:02 +0000 (17:00 +0000)
committerWerner Koch <wk@gnupg.org>
Sat, 13 Jun 1998 17:00:02 +0000 (17:00 +0000)
33 files changed:
cipher/ChangeLog
cipher/Makefile.am
cipher/blowfish.c
cipher/cipher.c
cipher/dsa.c
cipher/dsa.h
cipher/dynload.c
cipher/dynload.h
cipher/elgamal.c
cipher/elgamal.h
cipher/g10c.c [new file with mode: 0644]
cipher/md.c
cipher/md.h
cipher/misc.c [deleted file]
cipher/primegen.c
cipher/pubkey.c
doc/DETAILS
g10/g10.c
g10/getkey.c
g10/keydb.h
g10/keygen.c
g10/parse-packet.c
g10/seckey-cert.c
g10/sig-check.c
g10/trustdb.c
include/ChangeLog
include/cipher.h
include/distfiles
include/g10lib.h [new file with mode: 0644]
mpi/Makefile.am
mpi/g10m.c [new file with mode: 0644]
util/Makefile.am
util/g10u.c [new file with mode: 0644]

index 6e59455..760f52d 100644 (file)
@@ -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)
 
index 53ba749..04d1ef8 100644 (file)
@@ -35,7 +35,7 @@ libcipher_a_SOURCES = cipher.c        \
                 sha1.c         \
                 dsa.h          \
                 dsa.c          \
-                misc.c         \
+                g10c.c         \
                 smallprime.c
 
 
index ec686e1..65a408e 100644 (file)
@@ -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";
index 6ac4682..0649478 100644 (file)
@@ -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++;
index d1c15c4..20011da 100644 (file)
 #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;
+    }
+}
+
+
index 2d38a73..fe977a6 100644 (file)
 #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*/
index b40eb40..e0b2e77 100644 (file)
@@ -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;
index 78f41c6..69b5d8f 100644 (file)
@@ -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*/
index 7fad35c..b37c756 100644 (file)
 #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;
+    }
+}
+
+
index d253fbd..a4668ff 100644 (file)
 #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 (file)
index 0000000..c6f9402
--- /dev/null
@@ -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 <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#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 );
+}
+
+
index 4341b39..30d7e25 100644 (file)
 #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
index e55a99e..2d45a12 100644 (file)
@@ -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 (file)
index b81a4fa..0000000
+++ /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 <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#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;
-    }
-}
-
-
-
index 26d21ac..23aa1db 100644 (file)
@@ -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 );
index 0a4b343..3357ae1 100644 (file)
 #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] );
+    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;
+}
 
-    if( is_RSA( algo) )
-       return mpi_get_nbits( pkey[0] );
 
-    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;
-
-    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;
+    int i;
+
+    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;
-
-    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;
+    int i, rc;
+
+    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;
 }
 
index 7ff8e24..a9f0409 100644 (file)
@@ -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
index 94fb644..8f65f2e 100644 (file)
--- 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;
     }
 
 
index fb4a849..5f607ec 100644 (file)
@@ -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;
index 1cd6457..07d9115 100644 (file)
@@ -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 );
index 63c162f..8ad30bb 100644 (file)
@@ -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;
 
index 0ee6e7d..0cd4238 100644 (file)
@@ -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;
index 41a09b2..9ac19c8 100644 (file)
@@ -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;
     }
index a4c802c..0ef69b7 100644 (file)
@@ -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 );*/
index 3ebc831..bb4942c 100644 (file)
@@ -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 ) ) {
index 05b40fa..0df9e68 100644 (file)
@@ -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
index 3fe56c2..7913e4a 100644 (file)
@@ -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[];
 
index 35ca322..6257e96 100644 (file)
@@ -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 (file)
index 0000000..12e846c
--- /dev/null
@@ -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 */
index ead60a6..11a18bf 100644 (file)
@@ -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 (file)
index 0000000..79d5714
--- /dev/null
@@ -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 <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#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;
+}
+
index df60fbb..baef604 100644 (file)
@@ -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 (file)
index 0000000..1b0bc9d
--- /dev/null
@@ -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 <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#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 ); }
+