See ChangeLog: Sat Nov 13 17:44:23 CET 1999 Werner Koch
authorWerner Koch <wk@gnupg.org>
Sat, 13 Nov 1999 16:43:20 +0000 (16:43 +0000)
committerWerner Koch <wk@gnupg.org>
Sat, 13 Nov 1999 16:43:20 +0000 (16:43 +0000)
24 files changed:
cipher/ChangeLog
cipher/Makefile.am
cipher/blowfish.c
cipher/cast5.c
cipher/cipher.c
cipher/des.c
cipher/dsa.c
cipher/dynload.c
cipher/elgamal.c
cipher/g10c.c [deleted file]
cipher/md.c
cipher/primegen.c
cipher/pubkey.c
cipher/random.c
cipher/random.h
cipher/rndegd.c
cipher/rndunix.c
cipher/rndw32.c
cipher/twofish.c
src/ChangeLog
src/Makefile.am
src/gcrypt.h
src/global.c
src/sexp.c

index ea23ca1..6aed450 100644 (file)
@@ -1,3 +1,46 @@
+Sat Nov 13 17:44:23 CET 1999  Werner Koch  <wk@gnupg.de>
+
+       * pubkey.c (disable_pubkey_algo): Made static.
+       (gcry_pk_ctl): New.
+
+       * random.c (get_random_bits): Renamed to ...
+       (get_random_bytes): ... this and made static.
+       (gcry_random_bytes): New.
+       (gcry_random_bytes_secure): New.
+       (randomize_buffer): Renamed to ...
+       (gcry_randomize): ...this.
+
+       * md.c (gcry_md_hash_buffer): New.
+
+       * pubkey.c (gcry_pk_algo_info): 4 new commands.
+       (pubkey_get_npkey): Made static.
+       (pubkey_get_nskey): Made static.
+       (pubkey_get_nsig): Made static.
+       (pubkey_get_nenc): Made static.
+
+       * pubkey.c: Removed all G10ERR_xxx.
+       * cipher.c: Changed all GCRYERR_INV_ALGO to GCRYERR_INV_CIPHER_ALGO.
+       * md.c: Changed all GCRYERR_INV_ALGO to GCRYERR_INV_MD_ALGO.
+       * cast5.c (cast_setkey): Changed errocodes to GCRYERR_xxx.
+       * blowfish.c: Ditto.
+       * des.c: Ditto.
+       * twofish.c: Ditto.
+       * dsa.c: Ditto.
+       * elgamal.c: Ditto.
+
+       * g10c.c: Removed
+
+       * cipher.c (gcry_cipher_open): Replaced alloc functions and return NULL
+       if we are out of core.
+       * dynload.c: Replaced all memory allocation functions.
+       * md.c: Ditto.
+       * primegen.c: Ditto.
+       * pubkey.c: Ditto.
+       * random.c: Ditto.
+       * rndw32.c: Ditto.
+       * elgamal.c: Ditto.
+       * dsa.c: Ditto.
+
 Tue Oct 26 14:10:21 CEST 1999  Werner Koch  <wk@gnupg.de>
 
        * elgamal.c (sign): Hugh found strange code here. Replaced by BUG().
index e68ee19..23142d9 100644 (file)
@@ -57,7 +57,6 @@ libcipher_la_SOURCES = cipher.c  \
                 rmd.h          \
                 dsa.h          \
                 dsa.c          \
-                g10c.c         \
                 smallprime.c   \
                 construct.c
 
index 5a829d4..e7f047f 100644 (file)
@@ -35,7 +35,7 @@
 #include <string.h>
 #include <assert.h>
 #include "types.h"
-#include "errors.h"
+#include "g10lib.h"
 #include "blowfish.h"
 #include "dynload.h"
 
@@ -498,7 +498,7 @@ bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
            fprintf(stderr,"%s\n", selftest_failed );
     }
     if( selftest_failed )
-       return G10ERR_SELFTEST_FAILED;
+       return GCRYERR_SELFTEST;
 
     for(i=0; i < BLOWFISH_ROUNDS+2; i++ )
        c->p[i] = ps[i];
@@ -559,7 +559,7 @@ bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
        for( j=i+1; j < 256; j++) {
            if( (c->s0[i] == c->s0[j]) || (c->s1[i] == c->s1[j]) ||
                (c->s2[i] == c->s2[j]) || (c->s3[i] == c->s3[j]) )
-               return G10ERR_WEAK_KEY;
+               return GCRYERR_WEAK_KEY;
        }
     }
 
index 0e602bd..aaa0a42 100644 (file)
@@ -39,8 +39,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include "g10lib.h"
 #include "types.h"
-#include "errors.h"
 #include "cast5.h"
 
 
@@ -566,10 +566,10 @@ cast_setkey( CAST5_context *c, byte *key, unsigned keylen )
            fprintf(stderr,"CAST5 selftest failed (%s).\n", selftest_failed );
     }
     if( selftest_failed )
-       return G10ERR_SELFTEST_FAILED;
+       return GCRYERR_SELFTEST;
 
     if( keylen != 16 )
-       return G10ERR_WRONG_KEYLEN;
+       return GCRYERR_INV_KEYLEN;
 
     x[0] = key[0]  << 24 | key[1]  << 16 | key[2]  << 8 | key[3];
     x[1] = key[4]  << 24 | key[5]  << 16 | key[6]  << 8 | key[7];
index 277dd13..0a1ad60 100644 (file)
@@ -27,7 +27,6 @@
 
 #include "g10lib.h"
 #include "util.h"
-#include "errors.h"
 #include "cipher.h"
 #include "des.h"
 #include "blowfish.h"
@@ -289,12 +288,12 @@ check_cipher_algo( int algo )
           if( cipher_table[i].algo == algo ) {
                for(i=0; i < DIM(disabled_algos); i++ ) {
                   if( disabled_algos[i] == algo )
-                      return G10ERR_CIPHER_ALGO;
+                      return GCRYERR_INV_CIPHER_ALGO;
                }
                return 0; /* okay */
           }
     } while( load_cipher_modules() );
-    return G10ERR_CIPHER_ALGO;
+    return GCRYERR_INV_CIPHER_ALGO;
 }
 
 
@@ -356,13 +355,13 @@ gcry_cipher_open( int algo, int mode, unsigned int flags )
 
     /* check whether the algo is available */
     if( check_cipher_algo( algo ) ) {
-       set_lasterr( GCRYERR_INV_ALGO );
+       set_lasterr( GCRYERR_INV_CIPHER_ALGO );
        return NULL;
     }
 
     /* check flags */
     if( (flags & ~(GCRY_CIPHER_SECURE|GCRY_CIPHER_ENABLE_SYNC)) ) {
-       set_lasterr( GCRYERR_INV_ARG );
+       set_lasterr( GCRYERR_INV_CIPHER_ALGO );
        return NULL;
     }
 
@@ -386,17 +385,21 @@ gcry_cipher_open( int algo, int mode, unsigned int flags )
        /* FIXME: issue a warning when this mode is used */
        break;
       default:
-       set_lasterr( GCRYERR_INV_ALGO );
+       set_lasterr( GCRYERR_INV_CIPHER_ALGO );
        return NULL;
     }
 
     /* ? perform selftest here and mark this with a flag in cipher_table ? */
 
-    h = secure ? m_alloc_secure_clear( sizeof *h
+    h = secure ? g10_calloc_secure( 1, sizeof *h
                                       + cipher_table[idx].contextsize
                                       - sizeof(PROPERLY_ALIGNED_TYPE) )
-              : m_alloc_clear( sizeof *h + cipher_table[idx].contextsize
+              : g10_calloc( 1, sizeof *h + cipher_table[idx].contextsize
                                           - sizeof(PROPERLY_ALIGNED_TYPE)  );
+    if( !h ) {
+       set_lasterr( GCRYERR_NO_MEM );
+       return NULL;
+    }
     h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
     h->algo = algo;
     h->mode = mode;
@@ -420,7 +423,7 @@ gcry_cipher_close( GCRY_CIPHER_HD h )
        return;
     }
     h->magic = 0;
-    m_free(h);
+    g10_free(h);
 }
 
 
@@ -449,7 +452,7 @@ cipher_setiv( GCRY_CIPHER_HD c, const byte *iv, unsigned ivlen )
 
 
 static void
-do_ecb_encrypt( GCRY_CIPHER_HD c, byte *outbuf, byte *inbuf, unsigned nblocks )
+do_ecb_encrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nblocks )
 {
     unsigned n;
 
@@ -461,7 +464,7 @@ do_ecb_encrypt( GCRY_CIPHER_HD c, byte *outbuf, byte *inbuf, unsigned nblocks )
 }
 
 static void
-do_ecb_decrypt( GCRY_CIPHER_HD c, byte *outbuf, byte *inbuf, unsigned nblocks )
+do_ecb_decrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nblocks )
 {
     unsigned n;
 
@@ -473,7 +476,7 @@ do_ecb_decrypt( GCRY_CIPHER_HD c, byte *outbuf, byte *inbuf, unsigned nblocks )
 }
 
 static void
-do_cbc_encrypt( GCRY_CIPHER_HD c, byte *outbuf, byte *inbuf, unsigned nblocks )
+do_cbc_encrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nblocks )
 {
     unsigned int n;
     byte *ivp;
@@ -494,7 +497,7 @@ do_cbc_encrypt( GCRY_CIPHER_HD c, byte *outbuf, byte *inbuf, unsigned nblocks )
 }
 
 static void
-do_cbc_decrypt( GCRY_CIPHER_HD c, byte *outbuf, byte *inbuf, unsigned nblocks )
+do_cbc_decrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nblocks )
 {
     unsigned int n;
     byte *ivp;
@@ -517,7 +520,7 @@ do_cbc_decrypt( GCRY_CIPHER_HD c, byte *outbuf, byte *inbuf, unsigned nblocks )
 
 
 static void
-do_cfb_encrypt( GCRY_CIPHER_HD c, byte *outbuf, byte *inbuf, unsigned nbytes )
+do_cfb_encrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nbytes )
 {
     byte *ivp;
     size_t blocksize = c->blocksize;
@@ -561,7 +564,7 @@ do_cfb_encrypt( GCRY_CIPHER_HD c, byte *outbuf, byte *inbuf, unsigned nbytes )
 }
 
 static void
-do_cfb_decrypt( GCRY_CIPHER_HD c, byte *outbuf, byte *inbuf, unsigned nbytes )
+do_cfb_decrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nbytes )
 {
     byte *ivp;
     ulong temp;
@@ -624,7 +627,8 @@ do_cfb_decrypt( GCRY_CIPHER_HD c, byte *outbuf, byte *inbuf, unsigned nbytes )
  * Depending on the mode some some contraints apply to NBYTES.
  */
 static void
-cipher_encrypt( GCRY_CIPHER_HD c, byte *outbuf, byte *inbuf, unsigned nbytes )
+cipher_encrypt( GCRY_CIPHER_HD c, byte *outbuf,
+                                 const byte *inbuf, unsigned nbytes )
 {
     switch( c->mode ) {
       case GCRY_CIPHER_MODE_ECB:
@@ -680,7 +684,8 @@ gcry_cipher_encrypt( GCRY_CIPHER_HD h, byte *out, size_t outsize,
  * Depending on the mode some some contraints apply to NBYTES.
  */
 static void
-cipher_decrypt( GCRY_CIPHER_HD c, byte *outbuf, byte *inbuf, unsigned nbytes )
+cipher_decrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf,
+                                                       unsigned nbytes )
 {
     switch( c->mode ) {
       case GCRY_CIPHER_MODE_ECB:
@@ -760,7 +765,7 @@ gcry_cipher_ctl( GCRY_CIPHER_HD h, int cmd, void *buffer, size_t buflen)
         * integer with the algo number.
         */
        if( h || !buffer || buflen != sizeof(int) )
-           return set_lasterr( GCRYERR_INV_ARG );
+           return set_lasterr( GCRYERR_INV_CIPHER_ALGO );
        disable_cipher_algo( *(int*)buffer );
        break;
 
@@ -819,26 +824,26 @@ gcry_cipher_algo_info( int algo, int what, void *buffer, size_t *nbytes)
     switch( what ) {
       case GCRYCTL_GET_KEYLEN:
        if( buffer || nbytes ) {
-           set_lasterr( GCRYERR_INV_ARG );
+           set_lasterr( GCRYERR_INV_CIPHER_ALGO );
            break;
        }
        ui = cipher_get_keylen( algo );
        if( ui > 0 && ui <= 512 )
            return (int)ui/8;
        /* the only reason is an invalid algo or a strange blocksize */
-       set_lasterr( GCRYERR_INV_ALGO );
+       set_lasterr( GCRYERR_INV_CIPHER_ALGO );
        break;
 
       case GCRYCTL_GET_BLKLEN:
        if( buffer || nbytes ) {
-           set_lasterr( GCRYERR_INV_ARG );
+           set_lasterr( GCRYERR_INV_CIPHER_ALGO );
            break;
        }
        ui = cipher_get_blocksize( algo );
        if( ui > 0 && ui < 10000 )
            return (int)ui;
        /* the only reason is an invalid algo or a strange blocksize */
-       set_lasterr( GCRYERR_INV_ALGO );
+       set_lasterr( GCRYERR_INV_CIPHER_ALGO );
        break;
 
       case GCRYCTL_TEST_ALGO:
@@ -847,7 +852,7 @@ gcry_cipher_algo_info( int algo, int what, void *buffer, size_t *nbytes)
            break;
        }
        if( check_cipher_algo( algo ) ) {
-           set_lasterr( GCRYERR_INV_ALGO );
+           set_lasterr( GCRYERR_INV_CIPHER_ALGO );
            break;
        }
        return 0;
index c2ca3f8..af5b584 100644 (file)
 #include <stdio.h>
 #include <string.h>           /* memcpy, memcmp */
 #include "types.h"             /* for byte and u32 typedefs */
-#include "errors.h"
+#include "g10lib.h"
 #include "des.h"
 
 #if defined(__GNUC__) && defined(__GNU_LIBRARY__)
@@ -558,7 +558,7 @@ des_setkey (struct _des_ctx *ctx, const byte * key)
   int i;
 
   if( selftest_failed )
-    return G10ERR_SELFTEST_FAILED;
+    return GCRYERR_SELFTEST;
 
   des_key_schedule (key, ctx->encrypt_subkeys);
 
@@ -944,14 +944,14 @@ static int
 do_tripledes_setkey ( struct _tripledes_ctx *ctx, byte *key, unsigned keylen )
 {
     if( selftest_failed )
-       return G10ERR_SELFTEST_FAILED;
+       return GCRYERR_SELFTEST;
     if( keylen != 24 )
-       return G10ERR_WRONG_KEYLEN;
+       return GCRYERR_INV_KEYLEN;
 
     tripledes_set3keys ( ctx, key, key+8, key+16);
 
     if( is_weak_key( key ) || is_weak_key( key+8 ) || is_weak_key( key+16 ) )
-       return G10ERR_WEAK_KEY;
+       return GCRYERR_WEAK_KEY;
 
     return 0;
 }
index 5828b95..5a356c9 100644 (file)
@@ -23,6 +23,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#include "g10lib.h"
 #include "util.h"
 #include "mpi.h"
 #include "cipher.h"
@@ -77,7 +78,7 @@ gen_k( MPI q )
            progress('.');
 
        if( !rndbuf || nbits < 32 ) {
-           m_free(rndbuf);
+           g10_free(rndbuf);
            rndbuf = get_random_bits( nbits, 1, 1 );
        }
        else { /* change only some of the higher bits */
@@ -86,7 +87,7 @@ gen_k( MPI q )
             * maybe it is easier to do this directly in random.c */
            char *pp = get_random_bits( 32, 1, 1 );
            memcpy( rndbuf,pp, 4 );
-           m_free(pp);
+           g10_free(pp);
        }
        mpi_set_buffer( k, rndbuf, nbytes, 0 );
        if( mpi_test_bit( k, nbits-1 ) )
@@ -108,7 +109,7 @@ gen_k( MPI q )
        }
        break;  /* okay */
     }
-    m_free(rndbuf);
+    g10_free(rndbuf);
     if( DBG_CIPHER )
        progress('\n');
 
@@ -131,7 +132,7 @@ test_keys( DSA_secret_key *sk, unsigned qbits )
     /*mpi_set_bytes( test, qbits, get_random_byte, 0 );*/
     {  char *p = get_random_bits( qbits, 0, 0 );
        mpi_set_buffer( test, p, (qbits+7)/8, 0 );
-       m_free(p);
+       g10_free(p);
     }
 
     sign( out1_a, out1_b, test, sk );
@@ -202,12 +203,12 @@ generate( DSA_secret_key *sk, unsigned nbits, MPI **ret_factors )
        else { /* change only some of the higher bits (= 2 bytes)*/
            char *r = get_random_bits( 16, 2, 1 );
            memcpy(rndbuf, r, 16/8 );
-           m_free(r);
+           g10_free(r);
        }
        mpi_set_buffer( x, rndbuf, (qbits+7)/8, 0 );
        mpi_clear_highbit( x, qbits+1 );
     } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, h )<0 ) );
-    m_free(rndbuf);
+    g10_free(rndbuf);
     mpi_free( e );
     mpi_free( h );
 
@@ -347,7 +348,7 @@ dsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
     DSA_secret_key sk;
 
     if( algo != PUBKEY_ALGO_DSA )
-       return G10ERR_PUBKEY_ALGO;
+       return GCRYERR_INV_PK_ALGO;
 
     generate( &sk, nbits, retfactors );
     skey[0] = sk.p;
@@ -365,9 +366,9 @@ dsa_check_secret_key( int algo, MPI *skey )
     DSA_secret_key sk;
 
     if( algo != PUBKEY_ALGO_DSA )
-       return G10ERR_PUBKEY_ALGO;
+       return GCRYERR_INV_PK_ALGO;
     if( !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] )
-       return G10ERR_BAD_MPI;
+       return GCRYERR_BAD_MPI;
 
     sk.p = skey[0];
     sk.q = skey[1];
@@ -375,7 +376,7 @@ dsa_check_secret_key( int algo, MPI *skey )
     sk.y = skey[3];
     sk.x = skey[4];
     if( !check_secret_key( &sk ) )
-       return G10ERR_BAD_SECKEY;
+       return GCRYERR_BAD_SECRET_KEY;
 
     return 0;
 }
@@ -388,9 +389,9 @@ dsa_sign( int algo, MPI *resarr, MPI data, MPI *skey )
     DSA_secret_key sk;
 
     if( algo != PUBKEY_ALGO_DSA )
-       return G10ERR_PUBKEY_ALGO;
+       return GCRYERR_INV_PK_ALGO;
     if( !data || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] )
-       return G10ERR_BAD_MPI;
+       return GCRYERR_BAD_MPI;
 
     sk.p = skey[0];
     sk.q = skey[1];
@@ -410,17 +411,17 @@ dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey,
     DSA_public_key pk;
 
     if( algo != PUBKEY_ALGO_DSA )
-       return G10ERR_PUBKEY_ALGO;
+       return GCRYERR_INV_PK_ALGO;
     if( !data[0] || !data[1] || !hash
        || !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] )
-       return G10ERR_BAD_MPI;
+       return GCRYERR_BAD_MPI;
 
     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 GCRYERR_BAD_SIGNATURE;
     return 0;
 }
 
index e2c988e..962b398 100644 (file)
@@ -31,6 +31,7 @@
   #include <dl.h>
   #include <errno.h>
 #endif
+#include "g10lib.h"
 #include "util.h"
 #include "cipher.h"
 #include "dynload.h"
@@ -131,12 +132,12 @@ register_cipher_extension( const char *mainpgm, const char *fname )
            tmp = make_filename(fname, NULL);
        else
            tmp = make_filename(GNUPG_LIBDIR, fname, NULL);
-       el = m_alloc_clear( sizeof *el + strlen(tmp) );
+       el = g10_xcalloc( 1, sizeof *el + strlen(tmp) );
        strcpy(el->name, tmp );
-       m_free(tmp);
+       g10_free(tmp);
     }
     else {
-       el = m_alloc_clear( sizeof *el + strlen(fname) );
+       el = g10_xcalloc( 1, sizeof *el + strlen(fname) );
        strcpy(el->name, fname );
     }
     /* check whether we have a class hint */
@@ -152,7 +153,7 @@ register_cipher_extension( const char *mainpgm, const char *fname )
     for(r = extensions; r; r = r->next ) {
        if( !compare_filenames(r->name, el->name) ) {
            log_info("extension `%s' already registered\n", el->name );
-           m_free(el);
+           g10_free(el);
            return;
        }
        else if( r->internal )
@@ -180,7 +181,7 @@ register_internal_cipher_extension(
 {
     EXTLIST r, el;
 
-    el = m_alloc_clear( sizeof *el + strlen(module_id) );
+    el = g10_xcalloc( 1, sizeof *el + strlen(module_id) );
     strcpy(el->name, module_id );
     el->internal = 1;
 
@@ -188,7 +189,7 @@ register_internal_cipher_extension(
     for(r = extensions; r; r = r->next ) {
        if( !compare_filenames(r->name, el->name) ) {
            log_info("extension `%s' already registered\n", el->name );
-           m_free(el);
+           g10_free(el);
            return;
        }
     }
@@ -350,13 +351,13 @@ enum_gnupgext_digests( void **enum_context,
     ENUMCONTEXT *ctx;
 
     if( !*enum_context ) { /* init context */
-       ctx = m_alloc_clear( sizeof( *ctx ) );
+       ctx = g10_xcalloc( 1, sizeof( *ctx ) );
        ctx->r = extensions;
        ctx->reqalgo = *algo;
        *enum_context = ctx;
     }
     else if( !algo ) { /* release the context */
-       m_free(*enum_context);
+       g10_free(*enum_context);
        *enum_context = NULL;
        return 0;
     }
@@ -411,12 +412,12 @@ enum_gnupgext_ciphers( void **enum_context, int *algo,
                          void (**)( void *, byte *, byte *));
 
     if( !*enum_context ) { /* init context */
-       ctx = m_alloc_clear( sizeof( *ctx ) );
+       ctx = g10_xcalloc( 1, sizeof( *ctx ) );
        ctx->r = extensions;
        *enum_context = ctx;
     }
     else if( !algo ) { /* release the context */
-       m_free(*enum_context);
+       g10_free(*enum_context);
        *enum_context = NULL;
        return NULL;
     }
@@ -485,12 +486,12 @@ enum_gnupgext_pubkeys( void **enum_context, int *algo,
                           unsigned (**)( int , MPI * ) );
 
     if( !*enum_context ) { /* init context */
-       ctx = m_alloc_clear( sizeof( *ctx ) );
+       ctx = g10_xcalloc( 1, sizeof( *ctx ) );
        ctx->r = extensions;
        *enum_context = ctx;
     }
     else if( !algo ) { /* release the context */
-       m_free(*enum_context);
+       g10_free(*enum_context);
        *enum_context = NULL;
        return NULL;
     }
index 9f98ce2..48fe22a 100644 (file)
@@ -26,6 +26,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include "g10lib.h"
 #include "util.h"
 #include "mpi.h"
 #include "cipher.h"
@@ -79,7 +80,7 @@ test_keys( ELG_secret_key *sk, unsigned nbits )
     /*mpi_set_bytes( test, nbits, get_random_byte, 0 );*/
     {  char *p = get_random_bits( nbits, 0, 0 );
        mpi_set_buffer( test, p, (nbits+7)/8, 0 );
-       m_free(p);
+       g10_free(p);
     }
 
     encrypt( out1_a, out1_b, test, &pk );
@@ -119,7 +120,7 @@ gen_k( MPI p )
        if( DBG_CIPHER )
            progress('.');
        if( !rndbuf || nbits < 32 ) {
-           m_free(rndbuf);
+           g10_free(rndbuf);
            rndbuf = get_random_bits( nbits, 1, 1 );
        }
        else { /* change only some of the higher bits */
@@ -128,7 +129,7 @@ gen_k( MPI p )
             * maybe it is easier to do this directly in random.c */
            char *pp = get_random_bits( 32, 1, 1 );
            memcpy( rndbuf,pp, 4 );
-           m_free(pp);
+           g10_free(pp);
        }
        mpi_set_buffer( k, rndbuf, nbytes, 0 );
 
@@ -156,7 +157,7 @@ gen_k( MPI p )
        }
     }
   found:
-    m_free(rndbuf);
+    g10_free(rndbuf);
     if( DBG_CIPHER )
        progress('\n');
     mpi_free(p_1);
@@ -212,13 +213,13 @@ generate(  ELG_secret_key *sk, unsigned nbits, MPI **ret_factors )
            progress('.');
        if( rndbuf ) { /* change only some of the higher bits */
            if( nbits < 16 ) {/* should never happen ... */
-               m_free(rndbuf);
+               g10_free(rndbuf);
                rndbuf = get_random_bits( nbits, 2, 1 );
            }
            else {
                char *r = get_random_bits( 16, 2, 1 );
                memcpy(rndbuf, r, 16/8 );
-               m_free(r);
+               g10_free(r);
            }
        }
        else
@@ -226,7 +227,7 @@ generate(  ELG_secret_key *sk, unsigned nbits, MPI **ret_factors )
        mpi_set_buffer( x, rndbuf, (nbits+7)/8, 0 );
        mpi_clear_highbit( x, nbits+1 );
     } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, p_min1 )<0 ) );
-    m_free(rndbuf);
+    g10_free(rndbuf);
 
     y = mpi_alloc(nbits/BITS_PER_MPI_LIMB);
     mpi_powm( y, g, x, p );
@@ -443,7 +444,7 @@ elg_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
     ELG_secret_key sk;
 
     if( !is_ELGAMAL(algo) )
-       return G10ERR_PUBKEY_ALGO;
+       return GCRYERR_INV_PK_ALGO;
 
     generate( &sk, nbits, retfactors );
     skey[0] = sk.p;
@@ -460,16 +461,16 @@ elg_check_secret_key( int algo, MPI *skey )
     ELG_secret_key sk;
 
     if( !is_ELGAMAL(algo) )
-       return G10ERR_PUBKEY_ALGO;
+       return GCRYERR_INV_PK_ALGO;
     if( !skey[0] || !skey[1] || !skey[2] || !skey[3] )
-       return G10ERR_BAD_MPI;
+       return GCRYERR_BAD_MPI;
 
     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 GCRYERR_BAD_SECRET_KEY;
 
     return 0;
 }
@@ -482,9 +483,9 @@ elg_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
     ELG_public_key pk;
 
     if( !is_ELGAMAL(algo) )
-       return G10ERR_PUBKEY_ALGO;
+       return GCRYERR_INV_PK_ALGO;
     if( !data || !pkey[0] || !pkey[1] || !pkey[2] )
-       return G10ERR_BAD_MPI;
+       return GCRYERR_BAD_MPI;
 
     pk.p = pkey[0];
     pk.g = pkey[1];
@@ -501,10 +502,10 @@ elg_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
     ELG_secret_key sk;
 
     if( !is_ELGAMAL(algo) )
-       return G10ERR_PUBKEY_ALGO;
+       return GCRYERR_INV_PK_ALGO;
     if( !data[0] || !data[1]
        || !skey[0] || !skey[1] || !skey[2] || !skey[3] )
-       return G10ERR_BAD_MPI;
+       return GCRYERR_BAD_MPI;
 
     sk.p = skey[0];
     sk.g = skey[1];
@@ -521,9 +522,9 @@ elg_sign( int algo, MPI *resarr, MPI data, MPI *skey )
     ELG_secret_key sk;
 
     if( !is_ELGAMAL(algo) )
-       return G10ERR_PUBKEY_ALGO;
+       return GCRYERR_INV_PK_ALGO;
     if( !data || !skey[0] || !skey[1] || !skey[2] || !skey[3] )
-       return G10ERR_BAD_MPI;
+       return GCRYERR_BAD_MPI;
 
     sk.p = skey[0];
     sk.g = skey[1];
@@ -542,16 +543,16 @@ elg_verify( int algo, MPI hash, MPI *data, MPI *pkey,
     ELG_public_key pk;
 
     if( !is_ELGAMAL(algo) )
-       return G10ERR_PUBKEY_ALGO;
+       return GCRYERR_INV_PK_ALGO;
     if( !data[0] || !data[1] || !hash
        || !pkey[0] || !pkey[1] || !pkey[2] )
-       return G10ERR_BAD_MPI;
+       return GCRYERR_BAD_MPI;
 
     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 GCRYERR_BAD_SIGNATURE;
     return 0;
 }
 
diff --git a/cipher/g10c.c b/cipher/g10c.c
deleted file mode 100644 (file)
index de6a09c..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/* 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"
-
-
-/* FIXME: The modules should use functions from libgcrypt */
-
-
-const char *g10c_revision_string(int dummy) { return "$Revision$"; }
-
-MPI
-g10c_generate_secret_prime( unsigned nbits )
-{
-    return generate_secret_prime( nbits );
-}
-
-
-char *
-g10c_get_random_bits( unsigned nbits, int level, int secure )
-{
-    return (char*)get_random_bits( nbits, level, secure );
-}
-
index f0dc939..bb179b6 100644 (file)
@@ -28,7 +28,6 @@
 #include "g10lib.h"
 #include "util.h"
 #include "cipher.h"
-#include "errors.h"
 #include "dynload.h"
 #include "rmd.h"
 
@@ -93,13 +92,13 @@ new_list_item( int algo,
 {
     struct md_digest_list_s *r;
 
-    r = m_alloc_clear( sizeof *r );
+    r = g10_xcalloc( 1, sizeof *r );
     r->algo = algo,
     r->name = (*get_info)( algo, &r->contextsize,
                           &r->asnoid, &r->asnlen, &r->mdlen,
                           &r->init, &r->write, &r->final, &r->read );
     if( !r->name ) {
-       m_free(r);
+       g10_free(r);
        r = NULL;
     }
     return r;
@@ -230,7 +229,7 @@ check_digest_algo( int algo )
            if( r->algo == algo )
                return 0;
     } while( !r && load_digest_module(algo) );
-    return G10ERR_DIGEST_ALGO;
+    return GCRYERR_INV_MD_ALGO;
 }
 
 
@@ -267,8 +266,13 @@ md_open( int algo, int secure )
         / sizeof(PROPERLY_ALIGNED_TYPE) ) * sizeof(PROPERLY_ALIGNED_TYPE);
 
     /* allocate and set the Context pointer to the private data */
-    hd = secure ? m_alloc_secure( n + sizeof( struct gcry_md_context ) )
-               : m_alloc(        n + sizeof( struct gcry_md_context ) );
+    hd = secure ? g10_malloc_secure( n + sizeof( struct gcry_md_context ) )
+               : g10_malloc(        n + sizeof( struct gcry_md_context ) );
+    if( !hd ) {
+       set_lasterr( GCRYERR_NO_MEM );
+       return NULL;
+    }
+
     hd->ctx = ctx = (struct gcry_md_context*)( (char*)hd + n );
     /* setup the globally visible data (bctl in the diagram)*/
     hd->bufsize = n - sizeof( struct gcry_md_handle ) + 1;
@@ -315,13 +319,16 @@ md_enable( GCRY_MD_HD hd, int algo )
     } while( !r && load_digest_module( algo ) );
     if( !r ) {
        log_debug("md_enable: algorithm %d not available\n", algo );
-       return set_lasterr( GCRYERR_INV_ALGO );
+       return set_lasterr( GCRYERR_INV_MD_ALGO );
     }
     /* and allocate a new list entry */
-    ac = h->secure? m_alloc_secure( sizeof *ac + r->contextsize
+    ac = h->secure? g10_malloc_secure( sizeof *ac + r->contextsize
                                               - sizeof(r->context) )
-                 : m_alloc( sizeof *ac + r->contextsize
+                 : g10_malloc( sizeof *ac + r->contextsize
                                               - sizeof(r->context) );
+    if( !rc )
+       return set_lasterr( GCRYERR_NO_MEM );
+
     *ac = *r;
     ac->next = h->list;
     h->list = ac;
@@ -350,8 +357,13 @@ md_copy( GCRY_MD_HD ahd )
        md_write( ahd, NULL, 0 );
 
     n = (char*)ahd->ctx - (char*)ahd;
-    bhd = a->secure ? m_alloc_secure( n + sizeof( struct gcry_md_context ) )
-                   : m_alloc(        n + sizeof( struct gcry_md_context ) );
+    bhd = a->secure ? g10_malloc_secure( n + sizeof( struct gcry_md_context ) )
+                   : g10_malloc(        n + sizeof( struct gcry_md_context ) );
+    if( !bhd ) {
+       set_lasterr( GCRYERR_NO_MEM );
+       return NULL;
+    }
+
     bhd->ctx = b = (struct gcry_md_context*)( (char*)bhd + n );
     /* no need to copy the buffer due to the write above */
     assert( ahd->bufsize == (n - sizeof( struct gcry_md_handle ) + 1) );
@@ -363,9 +375,9 @@ md_copy( GCRY_MD_HD ahd )
     /* and now copy the complete list of algorithms */
     /* I know that the copied list is reversed, but that doesn't matter */
     for( ar=a->list; ar; ar = ar->next ) {
-       br = a->secure ? m_alloc_secure( sizeof *br + ar->contextsize
+       br = a->secure ? g10_xmalloc_secure( sizeof *br + ar->contextsize
                                               - sizeof(ar->context) )
-                      : m_alloc( sizeof *br + ar->contextsize
+                      : g10_xmalloc( sizeof *br + ar->contextsize
                                               - sizeof(ar->context) );
        memcpy( br, ar, sizeof(*br) + ar->contextsize
                                    - sizeof(ar->context) );
@@ -412,9 +424,9 @@ md_close(GCRY_MD_HD a)
        md_stop_debug(a);
     for(r=a->ctx->list; r; r = r2 ) {
        r2 = r->next;
-       m_free(r);
+       g10_free(r);
     }
-    m_free(a);
+    g10_free(a);
 }
 
 
@@ -555,8 +567,8 @@ md_digest( GCRY_MD_HD a, int algo, byte *buffer, int buflen )
 
     /* I don't want to change the interface, so I simply work on a copy
      * of the context (extra overhead - should be fixed)*/
-    context = a->ctx->secure ? m_alloc_secure( r->contextsize )
-                            : m_alloc( r->contextsize );
+    context = a->ctx->secure ? g10_xmalloc_secure( r->contextsize )
+                            : g10_xmalloc( r->contextsize );
     memcpy( context, r->context.c, r->contextsize );
     (*r->final)( context );
     digest = (*r->read)( context );
@@ -565,7 +577,7 @@ md_digest( GCRY_MD_HD a, int algo, byte *buffer, int buflen )
        buflen = r->mdlen;
     memcpy( buffer, digest, buflen );
 
-    m_free(context);
+    g10_free(context);
     return buflen;
 }
 #endif
@@ -581,6 +593,20 @@ gcry_md_get( GCRY_MD_HD hd, int algo, byte *buffer, int buflen )
 }
 
 
+/****************
+ * Shortcut function to hash a buffer with a given algo. The only supported
+ * algorithm is RIPE-MD. The supplied digest buffer must be large enough
+ * to store the resulting hash.  No error is returned, the function will
+ * abort on an invalite algo.  DISABLED_ALGOS are ignored here.
+ */
+void
+gcry_md_hash_buffer( int algo, char *digest, const char *buffer, size_t length)
+{
+    if( algo == GCRY_MD_RMD160 )
+       rmd160_hash_buffer( digest, buffer, length );
+    else
+       BUG();
+}
 
 static int
 md_get_algo( GCRY_MD_HD a )
@@ -636,7 +662,7 @@ gcry_md_get_algo_dlen( int algo )
       default: {
            int len = md_digest_length( algo );
            if( !len )
-               set_lasterr( GCRYERR_INV_ALGO );
+               set_lasterr( GCRYERR_INV_MD_ALGO );
            return 0;
        }
     }
@@ -695,7 +721,7 @@ gcry_md_algo_info( int algo, int what, void *buffer, size_t *nbytes)
            return -1;
        }
        if( check_digest_algo( algo ) ) {
-           set_lasterr( GCRYERR_INV_ALGO );
+           set_lasterr( GCRYERR_INV_MD_ALGO );
            return -1;
        }
        break;
index 9bf1085..ca8e3ee 100644 (file)
@@ -28,6 +28,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#include "g10lib.h"
 #include "util.h"
 #include "mpi.h"
 #include "cipher.h"
@@ -121,7 +122,7 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
     q_factor = mode==1? gen_prime( req_qbits, 0, 1 ) : NULL;
 
     /* allocate an array to hold the factors + 2 for later usage */
-    factors = m_alloc_clear( (n+2) * sizeof *factors );
+    factors = g10_xcalloc_clear( n+2, sizeof *factors );
 
     /* make a pool of 3n+5 primes (this is an arbitrary value) */
     m = n*3+5;
@@ -129,7 +130,7 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
        m += 5; /* need some more for DSA */
     if( m < 25 )
        m = 25;
-    pool = m_alloc_clear( m * sizeof *pool );
+    pool = g10_xcalloc( m , sizeof *pool );
 
     /* permutate over the pool of primes */
     count1=count2=0;
@@ -142,7 +143,7 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
                pool[i] = NULL;
            }
            /* init m_out_of_n() */
-           perms = m_alloc_clear( m );
+           perms = g10_xcalloc( 1, m );
            for(i=0; i < n; i++ ) {
                perms[i] = 1;
                pool[i] = gen_prime( fbits, 0, 1 );
@@ -158,7 +159,7 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
                    factors[j++] = pool[i];
                }
            if( i == n ) {
-               m_free(perms); perms = NULL;
+               g10_free(perms); perms = NULL;
                progress('!');
                goto next_try;  /* allocate new primes */
            }
@@ -213,7 +214,7 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
     }
 
     if( ret_factors ) { /* caller wants the factors */
-       *ret_factors = m_alloc_clear( (n+2) * sizeof **ret_factors);
+       *ret_factors = g10_xcalloc( n+2 , sizeof **ret_factors);
        if( mode == 1 ) {
            i = 0;
            (*ret_factors)[i++] = mpi_copy( q_factor );
@@ -264,11 +265,11 @@ generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
     if( !DBG_CIPHER )
        progress('\n');
 
-    m_free( factors ); /* (factors are shallow copies) */
+    g10_free( factors );  /* (factors are shallow copies) */
     for(i=0; i < m; i++ )
        mpi_free( pool[i] );
-    m_free( pool );
-    m_free(perms);
+    g10_free( pool );
+    g10_free(perms);
     mpi_free(val_2);
     return prime;
 }
@@ -292,7 +293,7 @@ gen_prime( unsigned  nbits, int secret, int randomlevel )
        for(i=0; small_prime_numbers[i]; i++ )
            no_of_small_prime_numbers++;
     }
-    mods = m_alloc( no_of_small_prime_numbers * sizeof *mods );
+    mods = g10_xmalloc( no_of_small_prime_numbers * sizeof *mods );
     /* make nbits fit into MPI implementation */
     nlimbs = (nbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB;
     val_2  = mpi_alloc_set_ui( 2 );
@@ -308,7 +309,7 @@ gen_prime( unsigned  nbits, int secret, int randomlevel )
        /* generate a random number */
        {   char *p = get_random_bits( nbits, randomlevel, secret );
            mpi_set_buffer( prime, p, (nbits+7)/8, 0 );
-           m_free(p);
+           g10_free(p);
        }
 
        /* set high order bit to 1, set low order bit to 1 */
@@ -352,7 +353,7 @@ gen_prime( unsigned  nbits, int secret, int randomlevel )
                    mpi_free(result);
                    mpi_free(pminus1);
                    mpi_free(prime);
-                   m_free(mods);
+                   g10_free(mods);
                    return ptest;
                }
            }
@@ -436,7 +437,7 @@ is_prime( MPI n, int steps, int *count )
            /*mpi_set_bytes( x, nbits-1, get_random_byte, 0 );*/
            {   char *p = get_random_bits( nbits, 0, 0 );
                mpi_set_buffer( x, p, (nbits+7)/8, 0 );
-               m_free(p);
+               g10_free(p);
            }
            /* make sure that the number is smaller than the prime
             * and keep the randomness of the high bit */
index 4561f2f..8d00d95 100644 (file)
 
 #include "g10lib.h"
 #include "util.h"
-#include "errors.h"
 #include "mpi.h"
 #include "cipher.h"
 #include "elgamal.h"
 #include "dsa.h"
 #include "dynload.h"
 
+/* FIXME: use set_lasterr() */
 
 #define TABLE_SIZE 10
 
@@ -58,31 +58,72 @@ struct pubkey_table_s {
 static struct pubkey_table_s pubkey_table[TABLE_SIZE];
 static int disabled_algos[TABLE_SIZE];
 
+static struct { const char* name; int algo;
+               const char* common_elements;
+               const char* public_elements;
+               const char* secret_elements;
+} algo_info_table[] = {
+       {  "dsa"            , PUBKEY_ALGO_DSA       , "pqgy", "", "x"    },
+       {  "rsa"            , PUBKEY_ALGO_RSA       , "ne",   "", "dpqu" },
+       {  "elg"            , PUBKEY_ALGO_ELGAMAL   , "pgy",  "", "x"    },
+       {  "openpgp-dsa"    , PUBKEY_ALGO_DSA       , "pqgy", "", "x"    },
+       {  "openpgp-rsa"    , PUBKEY_ALGO_RSA       , "pqgy", "", "x"    },
+       {  "openpgp-elg"    , PUBKEY_ALGO_ELGAMAL_E , "pgy",  "", "x"    },
+       {  "openpgp-elg-sig", PUBKEY_ALGO_ELGAMAL   , "pgy",  "", "x"    },
+       {  NULL }};
+
+static struct {
+    const char* name; int algo;
+    const char* elements;
+} sig_info_table[] = {
+       {  "dsa"            , PUBKEY_ALGO_DSA       , "rs" },
+       {  "rsa"            , PUBKEY_ALGO_RSA       , "s"  },
+       {  "elg"            , PUBKEY_ALGO_ELGAMAL   , "rs" },
+       {  "openpgp-dsa"    , PUBKEY_ALGO_DSA       , "rs" },
+       {  "openpgp-rsa"    , PUBKEY_ALGO_RSA       , "s"  },
+       {  "openpgp-elg-sig", PUBKEY_ALGO_ELGAMAL   , "rs" },
+       {  NULL }};
+
+static struct {
+    const char* name; int algo;
+    const char* elements;
+} enc_info_table[] = {
+       {  "elg"            , PUBKEY_ALGO_ELGAMAL   , "ab" },
+       {  "rsa"            , PUBKEY_ALGO_RSA       , "a"  },
+       {  "openpgp-rsa"    , PUBKEY_ALGO_RSA       , "a"  },
+       {  "openpgp-elg"    , PUBKEY_ALGO_ELGAMAL_E , "ab" },
+       {  "openpgp-elg-sig", PUBKEY_ALGO_ELGAMAL   , "ab" },
+       {  NULL }};
+
+
+static int pubkey_sign( int algo, MPI *resarr, MPI hash, MPI *skey );
+static int pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey,
+                     int (*cmp)(void *, MPI), void *opaque );
 
 static int
 dummy_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
-{ log_bug("no generate() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; }
+{ log_bug("no generate() for %d\n", algo ); return GCRYERR_INV_PK_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; }
+{ log_bug("no check_secret_key() for %d\n", algo ); return GCRYERR_INV_PK_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; }
+{ log_bug("no encrypt() for %d\n", algo ); return GCRYERR_INV_PK_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; }
+{ log_bug("no decrypt() for %d\n", algo ); return GCRYERR_INV_PK_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; }
+{ log_bug("no sign() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
 
 static int
 dummy_verify( int algo, MPI hash, MPI *data, MPI *pkey,
                int (*cmp)(void *, MPI), void *opaquev )
-{ log_bug("no verify() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; }
+{ log_bug("no verify() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
 
 static unsigned
 dummy_get_nbits( int algo, MPI *pkey )
@@ -269,7 +310,7 @@ gcry_pk_algo_name( int algo )
 }
 
 
-void
+static void
 disable_pubkey_algo( int algo )
 {
     int i;
@@ -284,38 +325,32 @@ disable_pubkey_algo( int algo )
 }
 
 
-int
-check_pubkey_algo( int algo )
-{
-    return check_pubkey_algo2( algo, 0 );
-}
-
 /****************
  * a use of 0 means: don't care
  */
-int
-check_pubkey_algo2( int algo, unsigned use )
+static int
+check_pubkey_algo( int algo, unsigned use )
 {
     int i;
 
     do {
        for(i=0; pubkey_table[i].name; i++ )
            if( pubkey_table[i].algo == algo ) {
-               if( (use & PUBKEY_USAGE_SIG)
-                   && !(pubkey_table[i].use & PUBKEY_USAGE_SIG) )
-                   return G10ERR_WR_PUBKEY_ALGO;
-               if( (use & PUBKEY_USAGE_ENC)
-                   && !(pubkey_table[i].use & PUBKEY_USAGE_ENC) )
-                   return G10ERR_WR_PUBKEY_ALGO;
+               if( (use & GCRY_PK_USAGE_SIGN)
+                   && !(pubkey_table[i].use & GCRY_PK_USAGE_SIGN) )
+                   return GCRYERR_WRONG_PK_ALGO;
+               if( (use & GCRY_PK_USAGE_ENCR)
+                   && !(pubkey_table[i].use & GCRY_PK_USAGE_ENCR) )
+                   return GCRYERR_WRONG_PK_ALGO;
 
                for(i=0; i < DIM(disabled_algos); i++ ) {
                    if( disabled_algos[i] == algo )
-                       return G10ERR_PUBKEY_ALGO;
+                       return GCRYERR_INV_PK_ALGO;
                }
                return 0; /* okay */
            }
     } while( load_pubkey_modules() );
-    return G10ERR_PUBKEY_ALGO;
+    return GCRYERR_INV_PK_ALGO;
 }
 
 
@@ -324,7 +359,7 @@ check_pubkey_algo2( int algo, unsigned use )
 /****************
  * Return the number of public key material numbers
  */
-int
+static int
 pubkey_get_npkey( int algo )
 {
     int i;
@@ -341,7 +376,7 @@ pubkey_get_npkey( int algo )
 /****************
  * Return the number of secret key material numbers
  */
-int
+static int
 pubkey_get_nskey( int algo )
 {
     int i;
@@ -358,7 +393,7 @@ pubkey_get_nskey( int algo )
 /****************
  * Return the number of signature material numbers
  */
-int
+static int
 pubkey_get_nsig( int algo )
 {
     int i;
@@ -375,7 +410,7 @@ pubkey_get_nsig( int algo )
 /****************
  * Return the number of encryption material numbers
  */
-int
+static int
 pubkey_get_nenc( int algo )
 {
     int i;
@@ -391,6 +426,9 @@ pubkey_get_nenc( int algo )
 
 /****************
  * Get the number of nbits from the public key
+ * FIXME: This should also take a S-Expt but must be optimized in
+ * some way becuase it is used in keylistsings ans such (store it with the
+ * S-Exp as some private data?)
  */
 unsigned
 pubkey_nbits( int algo, MPI *pkey )
@@ -419,7 +457,7 @@ pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
                return (*pubkey_table[i].generate)( algo, nbits,
                                                    skey, retfactors );
     } while( load_pubkey_modules() );
-    return G10ERR_PUBKEY_ALGO;
+    return GCRYERR_INV_PK_ALGO;
 }
 
 
@@ -433,7 +471,7 @@ pubkey_check_secret_key( int algo, MPI *skey )
            if( pubkey_table[i].algo == algo )
                return (*pubkey_table[i].check_secret_key)( algo, skey );
     } while( load_pubkey_modules() );
-    return G10ERR_PUBKEY_ALGO;
+    return GCRYERR_INV_PK_ALGO;
 }
 
 
@@ -462,7 +500,7 @@ pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
                goto ready;
            }
     } while( load_pubkey_modules() );
-    rc = G10ERR_PUBKEY_ALGO;
+    rc = GCRYERR_INV_PK_ALGO;
   ready:
     if( !rc && DBG_CIPHER ) {
        for(i=0; i < pubkey_get_nenc(algo); i++ )
@@ -501,7 +539,7 @@ pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
                goto ready;
            }
     } while( load_pubkey_modules() );
-    rc = G10ERR_PUBKEY_ALGO;
+    rc = GCRYERR_INV_PK_ALGO;
   ready:
     if( !rc && DBG_CIPHER ) {
        log_mpidump(" plain:", *result );
@@ -516,7 +554,7 @@ pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
  * should be an array of MPIs of size PUBKEY_MAX_NSIG (or less if the
  * algorithm allows this - check with pubkey_get_nsig() )
  */
-int
+static int
 pubkey_sign( int algo, MPI *resarr, MPI data, MPI *skey )
 {
     int i, rc;
@@ -535,7 +573,7 @@ pubkey_sign( int algo, MPI *resarr, MPI data, MPI *skey )
                goto ready;
            }
     } while( load_pubkey_modules() );
-    rc = G10ERR_PUBKEY_ALGO;
+    rc = GCRYERR_INV_PK_ALGO;
   ready:
     if( !rc && DBG_CIPHER ) {
        for(i=0; i < pubkey_get_nsig(algo); i++ )
@@ -548,7 +586,7 @@ pubkey_sign( int algo, MPI *resarr, MPI data, MPI *skey )
  * Verify a public key signature.
  * Return 0 if the signature is good
  */
-int
+static int
 pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey,
                    int (*cmp)(void *, MPI), void *opaquev )
 {
@@ -562,12 +600,171 @@ pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey,
                goto ready;
            }
     } while( load_pubkey_modules() );
-    rc = G10ERR_PUBKEY_ALGO;
+    rc = GCRYERR_INV_PK_ALGO;
   ready:
     return rc;
 }
 
 
+static void
+release_mpi_array( MPI *array )
+{
+    for( ; *array; array++ ) {
+       mpi_free(*array);
+       *array = NULL;
+    }
+}
+
+/****************
+ * Convert a S-Exp with either a private or a public key to our
+ * internal format. Currently we do only support the following
+ * algorithms:
+ *    dsa
+ *    rsa
+ *    openpgp-dsa
+ *    openpgp-rsa
+ *    openpgp-elg
+ *    openpgp-elg-sig
+ * Provide a SE with the first element be either "private-key" or
+ * or "public-key". the followed by a list with its first element
+ * be one of the above algorithm identifiers and the following
+ * elements are pairs with parameter-id and value.
+ * NOTE: we look through the list to find a list beginning with
+ * "private-key" or "public-key" - the first one found is used.
+ *
+ * FIXME: Allow for encrypted secret keys here.
+ *
+ * Returns: A pointer to an allocated array of MPIs if the return value is
+ *         zero; the caller has to release this array.
+ */
+static int
+sexp_to_key( GCRY_SEXP sexp, int want_private, MPI **retarray, int *retalgo)
+{
+    GCRY_SEXP list, l2;
+    const char *name;
+    const char *s;
+    size_t n;
+    int i, idx;
+    int algo;
+    const char *elems1, *elems2;
+    GCRY_MPI *array;
+
+    /* check that the first element is valid */
+    list = gcry_sexp_find_token( sexp, want_private? "private-key"
+                                                   :"public-key", 0 );
+    if( !list )
+       return GCRYERR_INV_OBJ; /* Does not contain a public- or private-key object */
+    list = gcry_sexp_cdr( list );
+    if( !list )
+       return GCRYERR_NO_OBJ; /* no cdr for the key object */
+    name = gcry_sexp_car_data( list, &n );
+    if( !name )
+       return GCRYERR_INV_OBJ; /* invalid structure of object */
+    for(i=0; (s=algo_info_table[i].name); i++ ) {
+       if( strlen(s) == n && !memcmp( s, name, n ) )
+           break;
+    }
+    if( !s )
+       return GCRYERR_INV_PK_ALGO; /* unknown algorithm */
+    algo = algo_info_table[i].algo;
+    elems1 = algo_info_table[i].common_elements;
+    elems2 = want_private? algo_info_table[i].secret_elements
+                        : algo_info_table[i].public_elements;
+    array = g10_calloc( (strlen(elems1)+strlen(elems2)+1, sizeof *array );
+    if( !array )
+       return GCRYERR_NO_MEM;
+
+    idx = 0;
+    for(s=elems1; *s; s++, idx++ ) {
+       l2 = gcry_sexp_find_token( list, s, 1 );
+       if( !l2 ) {
+           g10_free( array );
+           return GCRYERR_NO_OBJ; /* required parameter not found */
+       }
+       array[idx] = gcry_sexp_cdr_mpi( l2, GCRYMPI_FMT_USG );
+       if( !array[idx] ) {
+           g10_free( array );
+           return GCRYERR_INV_OBJ; /* required parameter is invalid */
+       }
+    }
+    for(s=elems2; *s; s++, idx++ ) {
+       l2 = gcry_sexp_find_token( list, s, 1 );
+       if( !l2 ) {
+           g10_free( array );
+           return GCRYERR_NO_OBJ; /* required parameter not found */
+       }
+       /* FIXME: put the MPI in secure memory when needed */
+       array[idx] = gcry_sexp_cdr_mpi( l2, GCRYMPI_FMT_USG );
+       if( !array[idx] ) {
+           g10_free( array );
+           return GCRYERR_INV_OBJ; /* required parameter is invalid */
+       }
+    }
+
+    *retarray = array;
+    *retalgo = algo;
+
+    return 0;
+}
+
+static int
+sexp_to_sig( GCRY_SEXP sexp, MPI **retarray, int *retalgo)
+{
+    GCRY_SEXP list, l2;
+    const char *name;
+    const char *s;
+    size_t n;
+    int i, idx;
+    int algo;
+    const char *elems;
+    GCRY_MPI *array;
+
+    /* check that the first element is valid */
+    list = gcry_sexp_find_token( sexp, "sig-val" , 0 );
+    if( !list )
+       return GCRYERR_INV_OBJ; /* Does not contain a signature value object */
+    list = gcry_sexp_cdr( list );
+    if( !list )
+       return GCRYERR_NO_OBJ; /* no cdr for the sig object */
+    name = gcry_sexp_car_data( list, &n );
+    if( !name )
+       return GCRYERR_INV_OBJ; /* invalid structure of object */
+    for(i=0; (s=sig_info_table[i].name); i++ ) {
+       if( strlen(s) == n && !memcmp( s, name, n ) )
+           break;
+    }
+    if( !s )
+       return GCRYERR_INV_PK_ALGO; /* unknown algorithm */
+    algo = sig_info_table[i].algo;
+    elems = sig_info_table[i].elements;
+    array = g10_calloc( (strlen(elems)+1) , sizeof *array );
+    if( !array )
+       return GCRYERR_NO_MEM;
+
+    idx = 0;
+    for(s=elems; *s; s++, idx++ ) {
+       l2 = gcry_sexp_find_token( list, s, 1 );
+       if( !l2 ) {
+           g10_free( array );
+           return GCRYERR_NO_OBJ; /* required parameter not found */
+       }
+       array[idx] = gcry_sexp_cdr_mpi( l2, GCRYMPI_FMT_USG );
+       if( !array[idx] ) {
+           g10_free( array );
+           return GCRYERR_INV_OBJ; /* required parameter is invalid */
+       }
+    }
+
+    *retarray = array;
+    *retalgo = algo;
+
+    return 0;
+}
+
+
+
+
+
 int
 gcry_pk_encrypt( GCRY_SEXP *result, GCRY_SEXP data, GCRY_SEXP pkey )
 {
@@ -582,26 +779,136 @@ gcry_pk_decrypt( GCRY_SEXP *result, GCRY_SEXP data, GCRY_SEXP skey )
     return 0;
 }
 
+
+
+/****************
+ * Create a signature.
+ *
+ * Caller has to provide a secret kez as the SEXP skey and data expressed
+ * as a SEXP list hash with only one emelennt which should instantly be
+ * available as a MPI. Later versions of this functions may provide padding
+ * and other things depending on data.
+ *
+ * Returns: 0 or an errorcode.
+ *         In case of 0 the function returns a new SEXP with the
+ *         signature value; the structure of this signature depends on the
+ *         other arguments but is always suitable to be passed to
+ *         gcry_pk_verify
+ */
 int
-gcry_pk_sign( GCRY_SEXP *result, GCRY_SEXP data, GCRY_SEXP skey )
+gcry_pk_sign( GCRY_SEXP *r_sig, GCRY_SEXP s_hash, GCRY_SEXP s_skey )
 {
+    MPI *skey, hash;
+    MPI *result;
+    int i, algo, rc;
+    const char *algo_name, *algo_elems;
     GCRY_SEXP s;
-    /* get the secret key */
-    s = NULL; /*gcry_sexp_find_token( skey, "private-key", 0 );*/
-    if( !s )
-       return -1; /* no private key */
-       /* ... */
+
+    rc = sexp_to_key( s_skey, 1, &skey, &algo );
+    if( rc )
+       return rc;
+
+    /* get the name and the required size of the result array */
+    for(i=0; (algo_name = sig_info_table[i].name); i++ ) {
+       if( sig_info_table[i].algo == algo )
+           break;
+    }
+    if( !algo_name ) {
+       release_mpi_array( skey );
+       return -4; /* oops: unknown algorithm */
+    }
+    algo_elems = sig_info_table[i].elements;
+
+    /* get the stuff we want to sign */
+    hash = gcry_sexp_car_mpi( s_hash, 0 );
+    if( !hash ) {
+       release_mpi_array( skey );
+       return -1; /* fixme: get a real errorcode for this */
+    }
+    result = g10_xcalloc_clear( (strlen(algo_elems)+1) , sizeof *result );
+    rc = pubkey_sign( algo, result, hash, skey );
+    release_mpi_array( skey );
+    mpi_free( hash );
+    if( rc ) {
+       g10_free( result );
+       return rc;
+    }
+
+    s = SEXP_NEW( algo_name, 0 );
+    for(i=0; algo_elems[i]; i++ ) {
+       char tmp[2];
+       tmp[0] = algo_elems[i];
+       tmp[1] = 0;
+       s = gcry_sexp_append( s, gcry_sexp_new_name_mpi( tmp, result[i] ) );
+    }
+    g10_free( result );
+    *r_sig = SEXP_CONS( SEXP_NEW( "sig-val", 0 ), s );
+    gcry_sexp_dump( *r_sig );
     return 0;
 }
 
+
+/****************
+ * Verify a sgnature.  Caller has to supply the public key pkey,
+ * the signature sig and his hashvalue data.  Public key has to be
+ * a standard public key given as an S-Exp, sig is a S-Exp as returned
+ * from gcry_pk_sign and data must be an S-Exp like the one in sign too.
+ */
 int
-gcry_pk_verify( GCRY_SEXP *result, GCRY_SEXP data, GCRY_SEXP pkey )
+gcry_pk_verify( GCRY_SEXP s_sig, GCRY_SEXP s_hash, GCRY_SEXP s_pkey )
 {
-       /* ... */
-    return 0;
+    MPI *pkey, hash, *sig;
+    int algo, sigalgo;
+    int rc;
+
+    rc = sexp_to_key( s_pkey, 0, &pkey, &algo );
+    if( rc )
+       return rc;
+    rc = sexp_to_sig( s_sig, &sig, &sigalgo );
+    if( rc ) {
+       release_mpi_array( pkey );
+       return rc;
+    }
+    if( algo != sigalgo ) {
+       release_mpi_array( pkey );
+       release_mpi_array( sig );
+       return -1; /* fixme: add real errornumber - algo does not match */
+    }
+
+    hash = gcry_sexp_car_mpi( s_hash, 0 );
+    if( !hash ) {
+       release_mpi_array( pkey );
+       release_mpi_array( sig );
+       return -1; /* fixme: get a real errorcode for this */
+    }
+
+    rc = pubkey_verify( algo, hash, sig, pkey, NULL, NULL );
+    release_mpi_array( pkey );
+    release_mpi_array( sig );
+    mpi_free(hash);
+
+    return rc;
 }
 
 
+int
+gcry_pk_ctl( int cmd, void *buffer, size_t buflen)
+{
+    switch( cmd ) {
+      case GCRYCTL_DISABLE_ALGO:
+       /* this one expects a buffer pointing to an
+        * integer with the algo number.
+        */
+       if( !buffer || buflen != sizeof(int) )
+           return set_lasterr( GCRYERR_INV_CIPHER_ALGO );
+       disable_pubkey_algo( *(int*)buffer );
+       break;
+
+      default:
+       return set_lasterr( GCRYERR_INV_OP );
+    }
+    return 0;
+}
 
 
 /****************
@@ -609,7 +916,9 @@ gcry_pk_verify( GCRY_SEXP *result, GCRY_SEXP data, GCRY_SEXP pkey )
  * WHAT select the kind of information returned:
  *  GCRYCTL_TEST_ALGO:
  *     Returns 0 when the specified algorithm is available for use.
- *     buffer and nbytes must be zero.
+ *     Buffer must be NULL, nbytes  may have the address of a variable
+ *     with the required usage of the algorithm. It may be 0 for don't
+ *     care or a combination of the GCRY_PK_USAGE_xxx flags;
  *
  * On error the value -1 is returned and the error reason may be
  * retrieved by gcry_errno().
@@ -623,17 +932,24 @@ int
 gcry_pk_algo_info( int algo, int what, void *buffer, size_t *nbytes)
 {
     switch( what ) {
-      case GCRYCTL_TEST_ALGO:
-       if( buffer || nbytes ) {
-           set_lasterr( GCRYERR_INV_ARG );
-           return -1;
-       }
-       if( check_pubkey_algo( algo ) ) {
-           set_lasterr( GCRYERR_INV_ALGO );
-           return -1;
+      case GCRYCTL_TEST_ALGO: {
+           int use = nbytes? *nbytes: 0;
+           if( buffer ) {
+               set_lasterr( GCRYERR_INV_ARG );
+               return -1;
+           }
+           if( check_pubkey_algo( algo, use ) ) {
+               set_lasterr( GCRYERR_INV_PK_ALGO );
+               return -1;
+           }
        }
        break;
 
+      case GCRYCTL_GET_ALGO_NPKEY: return pubkey_get_npkey( algo );
+      case GCRYCTL_GET_ALGO_NSKEY: return pubkey_get_nskey( algo );
+      case GCRYCTL_GET_ALGO_NSIGN: return pubkey_get_nsig( algo );
+      case GCRYCTL_GET_ALGO_NENCR: return pubkey_get_nenc( algo );
+
       default:
        set_lasterr( GCRYERR_INV_OP );
        return -1;
index 8ade26c..b8a09bb 100644 (file)
@@ -45,6 +45,7 @@
 #ifdef HAVE_GETRUSAGE
   #include <sys/resource.h>
 #endif
+#include "g10lib.h"
 #include "util.h"
 #include "rmd.h"
 #include "ttyio.h"
@@ -97,6 +98,7 @@ static int quick_test;
 static int faked_rng;
 
 
+static byte *get_random_bytes( size_t nbytes, int level, int secure );
 static void read_pool( byte *buffer, size_t length, int level );
 static void add_randomness( const void *buffer, size_t length, int source );
 static void random_poll(void);
@@ -123,10 +125,10 @@ initialize(void)
     /* The data buffer is allocated somewhat larger, so that
      * we can use this extra space (which is allocated in secure memory)
      * as a temporary hash buffer */
-    rndpool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN)
-                          : m_alloc_clear(POOLSIZE+BLOCKLEN);
-    keypool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN)
-                          : m_alloc_clear(POOLSIZE+BLOCKLEN);
+    rndpool = secure_alloc ? g10_xcalloc_secure(1,POOLSIZE+BLOCKLEN)
+                          : g10_xcalloc(1,POOLSIZE+BLOCKLEN);
+    keypool = secure_alloc ? g10_xcalloc_secure(1,POOLSIZE+BLOCKLEN)
+                          : g10_xcalloc(1,POOLSIZE+BLOCKLEN);
     is_initialized = 1;
     cipher_modules_constructor();
 }
@@ -170,11 +172,11 @@ quick_random_gen( int onoff )
  * for most usage, 2 is good for key generation stuff but may be very slow.
  */
 void
-randomize_buffer( byte *buffer, size_t length, int level )
+gcry_randomize( byte *buffer, size_t length, enum gcry_random_level level )
 {
-    char *p = get_random_bits( length*8, level, 1 );
+    char *p = get_random_bytes( length, level, 1 );
     memcpy( buffer, p, length );
-    m_free(p);
+    g10_free(p);
 }
 
 
@@ -191,11 +193,10 @@ random_is_faked()
  * caller must free the buffer.
  * Note: The returned value is rounded up to bytes.
  */
-byte *
-get_random_bits( size_t nbits, int level, int secure )
+static byte *
+get_random_bytes( size_t nbytes, int level, int secure )
 {
     byte *buf, *p;
-    size_t nbytes = (nbits+7)/8;
 
     if( quick_test && level > 1 )
        level = 1;
@@ -209,7 +210,8 @@ get_random_bits( size_t nbits, int level, int secure )
        rndstats.ngetbytes2++;
     }
 
-    buf = secure && secure_alloc ? m_alloc_secure( nbytes ) : m_alloc( nbytes );
+    buf = secure && secure_alloc ? g10_xmalloc_secure( nbytes )
+                                : g10_xmalloc( nbytes );
     for( p = buf; nbytes > 0; ) {
        size_t n = nbytes > POOLSIZE? POOLSIZE : nbytes;
        read_pool( p, n, level );
@@ -219,6 +221,18 @@ get_random_bits( size_t nbits, int level, int secure )
     return buf;
 }
 
+void *
+gcry_random_bytes( size_t nbytes, enum gcry_random_level level )
+{
+    return get_random_bytes( nbytes, level, 0 );
+}
+
+void *
+gcry_random_bytes_secure( size_t nbytes, enum gcry_random_level level )
+{
+    return get_random_bytes( nbytes, level, 1 );
+}
+
 
 /****************
  * Mix the pool
@@ -461,7 +475,7 @@ gather_faked( void (*add)(const void*, size_t, int), int requester,
       #endif
     }
 
-    p = buffer = m_alloc( length );
+    p = buffer = g10_xmalloc( length );
     n = length;
   #ifdef HAVE_RAND
     while( n-- )
@@ -471,7 +485,7 @@ gather_faked( void (*add)(const void*, size_t, int), int requester,
        *p++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1);
   #endif
     add_randomness( buffer, length, requester );
-    m_free(buffer);
+    g10_free(buffer);
     return 0; /* okay */
 }
 
index 649325c..9a7dd8f 100644 (file)
@@ -27,7 +27,6 @@ void random_dump_stats(void);
 void secure_random_alloc(void);
 int  quick_random_gen( int onoff );
 int  random_is_faked(void);
-void randomize_buffer( byte *buffer, size_t length, int level );
 byte *get_random_bits( size_t nbits, int level, int secure );
 void fast_random_poll( void );
 
index 7f2598f..87d75cf 100644 (file)
@@ -31,6 +31,7 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 #include "types.h"
+#include "g10lib.h"
 #include "util.h"
 #include "ttyio.h"
 #include "dynload.h"
@@ -126,7 +127,7 @@ gather_random( void (*add)(const void*, size_t, int), int requester,
        if( connect( fd, (struct sockaddr*)&addr, addr_len) == -1 )
            g10_log_fatal("can't connect to `%s': %s\n",
                                                    name, strerror(errno) );
-       m_free(name);
+       g10_free(name);
     }
     do_restart = 0;
 
index 46f80ea..36482df 100644 (file)
@@ -44,6 +44,8 @@
   code base to be maintained */
 
 
+  /* Fixme: We use plain mallocs here beucase it may be used as a module
+   * should be changed. *
 
 /* General includes */
 
index 032d666..d7801e3 100644 (file)
@@ -28,6 +28,7 @@
 #include <windows.h>
 
 #include "types.h"
+#include "g10lib.h"
 #include "util.h"
 #include "dynload.h"
 
@@ -126,7 +127,7 @@ load_and_init_winseed( void )
     g10_log_info("fast buffer size=%u\n", n2);
 
     entropy_buffer_size =  n1 > n2? n1: n2;
-    entropy_buffer = m_alloc( entropy_buffer_size );
+    entropy_buffer = g10_xmalloc( entropy_buffer_size );
     g10_log_info("using a buffer of size=%u\n", entropy_buffer_size );
 
     return;
index 182f18c..42eed8b 100644 (file)
@@ -27,8 +27,8 @@
 #include <string.h> /* for memcmp() */
 
 #include "types.h"  /* for byte and u32 typedefs */
+#include "g10lib.h"
 #include "util.h"
-#include "errors.h"
 #include "dynload.h"
 
 
@@ -574,7 +574,7 @@ twofish_setkey (TWOFISH_context *ctx, const byte *key, const unsigned keylen)
 
     /* Check key length. */
     if( ( ( keylen - 16 ) | 16 ) != 16 )
-       return G10ERR_WRONG_KEYLEN;
+       return GCRYERR_INV_KEYLEN;
 
     /* Do self-test if necessary. */
     if (!initialized) {
@@ -584,7 +584,7 @@ twofish_setkey (TWOFISH_context *ctx, const byte *key, const unsigned keylen)
         fprintf(stderr, "%s\n", selftest_failed );
     }
     if( selftest_failed )
-       return G10ERR_SELFTEST_FAILED;
+       return GCRYERR_SELFTEST;
 
     /* Compute the first two words of the S vector.  The magic numbers are
      * the entries of the RS matrix, preprocessed through poly_to_exp. The
index 29f9c8b..778a003 100644 (file)
@@ -1,3 +1,8 @@
+Sat Nov 13 17:44:23 CET 1999  Werner Koch  <wk@gnupg.de>
+
+       * gloabl.c (gcry_control): Add cases for dumping random
+       and secmem stats.
+
 Tue Oct 26 14:10:21 CEST 1999  Werner Koch  <wk@gnupg.de>
 
        * pkapi.c: Removed.
index aaafb89..eece892 100644 (file)
@@ -5,21 +5,21 @@ INCLUDES =  -I$(top_srcdir)/include -I$(top_srcdir)/intl
 
 lib_LTLIBRARIES = libgcrypt.la
 
-### noinst_PROGRAMS = sexp
-### sexp_SOURCES = sexp.c mpiapi.c
-### sexp_LDADD =  ../cipher/libcipher.la ../mpi/libmpi.la  ../util/libutil.la ./libgcrypt.la @INTLLIBS@
+#noinst_PROGRAMS = sexp
+#sexp_SOURCES = sexp.c mpiapi.c
+#sexp_LDADD =  ../cipher/libcipher.la ../mpi/libmpi.la ../util/libutil.la ./libgcrypt.la @INTLLIBS@
 
 
 libgcrypt_la_LDFLAGS = -version-info 0:0:0 -export-symbols libgcrypt.sym
 libgcrypt_la_SOURCES =  gcrypt.h \
                         misc.c  \
                         global.c \
+                        sexp.c \
                         mpiapi.c
 
 libgcrypt_la_DEPENDENCIES = libgcrypt.sym
 libgcrypt_la_LIBADD = ../cipher/libcipher.la  \
-                     ../mpi/libmpi.la        \
-                     ../util/libutil.la
+                     ../mpi/libmpi.la
 
 BUILT_SOURCES = libgcrypt.sym
 
index bc0e440..de5f05a 100644 (file)
@@ -34,25 +34,44 @@ extern "C" {
   #define HAVE_BYTE_TYPEDEF
 #endif
 
+struct gcry_mpi;
+typedef struct gcry_mpi *GCRY_MPI;
+
 /*******************************************
  *                                        *
  *  error handling etc.                   *
  *                                        *
  *******************************************/
 
+/* FIXME: We should use the same values as they were used in GnuPG 1.0.
+ *       gpg --status-fd may print some of these values */
 enum {
     GCRYERR_SUCCESS = 0,    /* "no error" */
     GCRYERR_GENERAL = 1,    /* catch all the other errors code */
-    GCRYERR_INV_OP = 2,     /* invalid operation code or ctl command */
-    GCRYERR_NOMEM = 3,     /* out of core */
-    GCRYERR_INV_ALGO = 4,   /* invalid algorithm */
-    GCRYERR_INV_ARG = 5,    /* invalid argument */
-    GCRYERR_INTERNAL = 6,   /* internal error */
-    GCRYERR_EOF = 7,       /* (-1) is remapped to this value */
-    GCRYERR_TOO_SHORT = 8,  /* provided buffer too short */
-    GCRYERR_TOO_LARGE = 9,  /* object is too large */
-    GCRYERR_INV_OBJ = 10,   /* an object is not valid */
-    GCRYERR_WEAK_KEY = 11,  /* weak encryption key */
+
+    GCRYERR_INV_PK_ALGO = 4, /* invalid public key algorithm */
+    GCRYERR_INV_MD_ALGO = 5, /* invalid message digest algorithm */
+    GCRYERR_BAD_PUBLIC_KEY = 6, /* Bad public key */
+    GCRYERR_BAD_SECRET_KEY = 7, /* Bad secret key */
+    GCRYERR_BAD_SIGNATURE = 8, /* Bad signature */
+
+    GCRYERR_INV_CIPHER_ALGO = 12, /* invalid cipher algorithm */
+    GCRYERR_BAD_MPI = 30,
+    GCRYERR_WRONG_PK_ALGO = 41, /* wrong public key algorithm */
+    GCRYERR_WEAK_KEY = 43,  /* weak encryption key */
+    GCRYERR_INV_KEYLEN = 44,  /* invalid length of a key*/
+    GCRYERR_INV_ARG = 45,    /* invalid argument */
+    GCRYERR_SELFTEST = 50,     /* selftest failed */
+
+    /* error codes not used in GnuPG 1.0 */
+    GCRYERR_INV_OP = 61,     /* invalid operation code or ctl command */
+    GCRYERR_NO_MEM = 62,     /* out of core */
+    GCRYERR_INTERNAL = 63,   /* internal error */
+    GCRYERR_EOF = 64,       /* (-1) is remapped to this value */
+    GCRYERR_INV_OBJ = 65,    /* an object is not valid */
+    GCRYERR_TOO_SHORT = 66,  /* provided buffer too short */
+    GCRYERR_TOO_LARGE = 67,  /* object is too large */
+    GCRYERR_NO_OBJ = 68,     /* Missign item in an object */
 };
 
 
@@ -72,6 +91,12 @@ enum gcry_ctl_cmds {
     GCRYCTL_GET_ASNOID = 10,
     GCRYCTL_ENABLE_ALGO = 11,
     GCRYCTL_DISABLE_ALGO = 12,
+    GCRYCTL_DUMP_RANDOM_STATS = 13,
+    GCRYCTL_DUMP_SECMEM_STATS = 14,
+    GCRYCTL_GET_ALGO_NPKEY = 15,
+    GCRYCTL_GET_ALGO_NSKEY = 16,
+    GCRYCTL_GET_ALGO_NSIGN = 17,
+    GCRYCTL_GET_ALGO_NENCR = 18,
 };
 
 int gcry_control( enum gcry_ctl_cmds, ... );
@@ -94,14 +119,31 @@ enum gcry_sexp_format {
 };
 
 
-GCRY_SEXP gcry_sexp_new( const char *buffer, size_t length );
-void gcry_sexp_release( GCRY_SEXP sexp );
+GCRY_SEXP gcry_sexp_new_data( const char *buffer, size_t length );
+GCRY_SEXP gcry_sexp_new_mpi( GCRY_MPI mpi );
+GCRY_SEXP gcry_sexp_new_name_data( const char *name,
+                                  const char *buffer, size_t length );
+GCRY_SEXP gcry_sexp_new_name_mpi( const char *name, GCRY_MPI mpi );
+void     gcry_sexp_release( GCRY_SEXP sexp );
+void     gcry_sexp_dump( GCRY_SEXP a );
 GCRY_SEXP gcry_sexp_cons( GCRY_SEXP a, GCRY_SEXP b );
 GCRY_SEXP gcry_sexp_vlist( GCRY_SEXP a, ... );
-int  gcry_sexp_sscan( GCRY_SEXP *retsexp, const char *buffer,
+GCRY_SEXP gcry_sexp_append( GCRY_SEXP a, GCRY_SEXP n );
+GCRY_SEXP gcry_sexp_prepend( GCRY_SEXP a, GCRY_SEXP n );
+int      gcry_sexp_sscan( GCRY_SEXP *retsexp, const char *buffer,
                               size_t length, size_t *erroff );
-size_t gcry_sexp_sprint( GCRY_SEXP sexp, int mode, char *buffer,
+size_t     gcry_sexp_sprint( GCRY_SEXP sexp, int mode, char *buffer,
                                                size_t maxlength );
+GCRY_SEXP   gcry_sexp_find_token( GCRY_SEXP list,
+                                 const char *tok, size_t toklen );
+GCRY_SEXP   gcry_sexp_car( GCRY_SEXP list );
+GCRY_SEXP   gcry_sexp_cdr( GCRY_SEXP list );
+const char *gcry_sexp_car_data( GCRY_SEXP list, size_t *datalen );
+const char *gcry_sexp_cdr_data( GCRY_SEXP list, size_t *datalen );
+GCRY_MPI    gcry_sexp_car_mpi( GCRY_SEXP list, int mpifmt );
+GCRY_MPI    gcry_sexp_cdr_mpi( GCRY_SEXP list, int mpifmt );
+
+
 
 #ifndef GCRYPT_NO_SEXP_MACROS
 #define SEXP           GCRY_SEXP
@@ -117,16 +159,15 @@ size_t gcry_sexp_sprint( GCRY_SEXP sexp, int mode, char *buffer,
  *******************************************/
 
 enum gcry_mpi_format {
-    GCRYMPI_FMT_STD = 0,    /* twos complement stored without length */
-    GCRYMPI_FMT_PGP = 1,    /* As used by OpenPGP */
-    GCRYMPI_FMT_SSH = 2,    /* As used by SSH (same as 0 but with length)*/
-    GCRYMPI_FMT_HEX = 3,    /* hex format */
-    GCRYMPI_FMT_USG = 4,    /* like STD but this is an unsigned one */
+    GCRYMPI_FMT_NONE= 0,
+    GCRYMPI_FMT_STD = 1,    /* twos complement stored without length */
+    GCRYMPI_FMT_PGP = 2,    /* As used by OpenPGP */
+    GCRYMPI_FMT_SSH = 3,    /* As used by SSH (same as 0 but with length)*/
+    GCRYMPI_FMT_HEX = 4,    /* hex format */
+    GCRYMPI_FMT_USG = 5,    /* like STD but this is an unsigned one */
 };
 
 
-struct gcry_mpi;
-typedef struct gcry_mpi *GCRY_MPI;
 
 GCRY_MPI gcry_mpi_new( unsigned int nbits );
 GCRY_MPI gcry_mpi_snew( unsigned int nbits );
@@ -175,7 +216,8 @@ enum gcry_cipher_algos {
     GCRY_CIPHER_CAST5      = 3,
     GCRY_CIPHER_BLOWFISH    = 4,
     GCRY_CIPHER_SAFER_SK128 = 5,
-    GCRY_CIPHER_DES_SK     = 6
+    GCRY_CIPHER_DES_SK     = 6,
+    GCRY_CIPHER_TWOFISH     = 10,
 };
 
 enum gcry_cipher_modes {
@@ -225,11 +267,25 @@ int gcry_cipher_decrypt( GCRY_CIPHER_HD h, byte *out, size_t outsize,
  *******  asymmetric cipher functions  *******
  *********************************************/
 
+enum gcry_pk_algos {
+    GCRY_PK_RSA = 1,
+    GCRY_PK_RSA_E = 2,     /* use only for OpenPGP */
+    GCRY_PK_RSA_S = 3,     /* use only for OpenPGP */
+    GCRY_PK_ELG_E = 16,     /* use only for OpenPGP */
+    GCRY_PK_DSA   = 17,
+    GCRY_PK_ELG   = 20,
+};
+
+/* Flags describing usage capabilites/request of a PK algorithm */
+#define GCRY_PK_USAGE_SIGN 1
+#define GCRY_PK_USAGE_ENCR 2
+
 int gcry_pk_encrypt( GCRY_SEXP *result, GCRY_SEXP data, GCRY_SEXP pkey );
 int gcry_pk_decrypt( GCRY_SEXP *result, GCRY_SEXP data, GCRY_SEXP skey );
 int gcry_pk_sign(    GCRY_SEXP *result, GCRY_SEXP data, GCRY_SEXP skey );
-int gcry_pk_verify(  GCRY_SEXP *result, GCRY_SEXP data, GCRY_SEXP pkey );
+int gcry_pk_verify(  GCRY_SEXP sigval, GCRY_SEXP data, GCRY_SEXP pkey );
 
+int gcry_pk_ctl( int cmd, void *buffer, size_t buflen);
 int gcry_pk_algo_info( int algo, int what, void *buffer, size_t *nbytes);
 const char *gcry_pk_algo_name( int algo );
 int gcry_pk_map_name( const char* name );
@@ -273,6 +329,8 @@ void gcry_md_reset( GCRY_MD_HD hd );
 int gcry_md_ctl( GCRY_MD_HD hd, int cmd, byte *buffer, size_t buflen);
 void gcry_md_write( GCRY_MD_HD hd, const byte *buffer, size_t length);
 byte *gcry_md_read( GCRY_MD_HD hd, int algo );
+void gcry_md_hash_buffer( int algo, char *digest,
+                         const char *buffer, size_t length);
 int gcry_md_get_algo( GCRY_MD_HD hd );
 unsigned int gcry_md_get_algo_dlen( int algo );
 /*??int gcry_md_get( GCRY_MD_HD hd, int algo, byte *buffer, int buflen );*/
@@ -298,138 +356,20 @@ int gcry_md_map_name( const char* name );
            gcry_md_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL )
 
 /*****************************************
- *******  miscellaneous functions  *******
+ *******  miscellaneous stuff  **********
  *****************************************/
 
-#if 0
-const char *g10m_revision_string(int mode);
-const char *g10c_revision_string(int mode);
-const char *g10u_revision_string(int mode);
-
-MPI   g10c_generate_secret_prime( unsigned nbits );
-char *g10c_get_random_bits( unsigned nbits, int level, int secure );
-
-
-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 );
-#endif
+void gcry_randomize( byte *buffer, size_t length,
+                    enum gcry_random_level level );
+void *gcry_random_bytes( size_t nbytes, enum gcry_random_level level );
+void *gcry_random_bytes_secure( size_t nbytes, enum gcry_random_level level );
 
-/***************************
- *******  constants  *******
- **************************/
-#if 0
-#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_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 for 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
-#endif
 
-/***********************************************
- *                                            *
- *   Some very handy macros                   *
- *                                            *
- ***********************************************/
 #ifndef GCRYPT_NO_MPI_MACROS
-
-typedef struct gcry_mpi *MPI;
-
+  typedef struct gcry_mpi *MPI;
 #endif /* GCRYPT_NO_MPI_MACROS */
 
 #ifdef __cplusplus
 }
 #endif
-
-
-/*****************************************
- ******** Stuff to be changed ************
- *****************************************/
-
-/*-- cipher/pubkey.c --*/
-#define PUBKEY_MAX_NPKEY  4
-#define PUBKEY_MAX_NSKEY  6
-#define PUBKEY_MAX_NSIG   2
-#define PUBKEY_MAX_NENC   2
-
-#ifndef DID_MPI_TYPEDEF
- typedef struct gcry_mpi * MPI;
- #define DID_MPI_TYPEDEF
-#endif
-
-int string_to_pubkey_algo( const char *string );
-const char * pubkey_algo_to_string( int algo );
-void disable_pubkey_algo( int algo );
-int check_pubkey_algo( int algo );
-int check_pubkey_algo2( int algo, unsigned use );
-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,
-                     int (*cmp)(void *, MPI), void *opaque );
-
-
-
-
-/*-- primegen.c --*/
-MPI generate_secret_prime( unsigned nbits );
-MPI generate_public_prime( unsigned nbits );
-MPI generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
-                                          MPI g, MPI **factors );
-
-
-
 #endif /* _GCRYPT_H */
index 7c5e21b..72206b4 100644 (file)
@@ -33,15 +33,25 @@ static int last_ec; /* fixme: make thread safe */
 int
 gcry_control( enum gcry_ctl_cmds cmd, ... )
 {
-  #if 0
     switch( cmd ) {
+     #if 0
       case GCRYCTL_NO_MEM_IS_FATAL:
        break;
       case GCRYCTL_SET_FATAL_FNC:
        break;
+     #endif
+      case GCRYCTL_DUMP_RANDOM_STATS:
+       random_dump_stats();
+       break;
+
+      case GCRYCTL_DUMP_SECMEM_STATS:
+       secmem_dump_stats();
+       break;
+
+      default:
+       return GCRYERR_INV_OP;
     }
-  #endif
-    return GCRYERR_INV_OP;
+    return 0;
 }
 
 int
@@ -58,11 +68,28 @@ gcry_strerror( int ec )
 
     if( ec == -1 )
        ec = gcry_errno();
+  #define X(n,a) case GCRYERR_##n : s = a; break;
     switch( ec ) {
+      X(SUCCESS,       N_("no error"))
+      X(GENERAL,       N_("general error"))
+      X(INV_OP,        N_("invalid operation code or ctl command"))
+      X(NOMEM,         N_("out of core"))
+      X(INV_ARG,       N_("invalid argument"))
+      X(INTERNAL,      N_("internal error"))
+      X(EOF,           N_("EOF"))
+      X(TOO_SHORT,     N_("provided buffer too short"))
+      X(TOO_LARGE,     N_("object is too large"))
+      X(INV_OBJ,       N_("an object is not valid"))
+      X(WEAK_KEY,      N_("weak encryption key"))
+      X(INV_PK_ALGO,   N_("invalid public key algorithm"))
+      X(INV_CIPHER_ALGO,N_("invalid cipher algorithm"))
+      X(INV_MD_ALGO,   N_("invalid hash algorithm"))
+      X(WRONG_PK_ALGO, N_("unusable public key algorithm"))
       default:
        sprintf( buf, "ec=%d", ec );
        s = buf;
     }
+  #undef X
     return s;
 }
 
@@ -75,4 +102,85 @@ set_lasterr( int ec )
     return ec;
 }
 
+void
+g10_free( void *p )
+{
+    if( p )
+       m_free(p);
+}
+
+void *
+g10_malloc( size_t n )
+{
+    return m_alloc( n );
+}
+
+void *
+g10_malloc_secure( size_t n )
+{
+    return m_alloc_secure( n );
+}
+
+void *
+g10_calloc( size_t n, size_t m )
+{
+    void *p = g10_malloc( n*m );
+    if( p )
+       memset( p, 0, n*m );
+    return p;
+}
+
+void *
+g10_calloc_secure( size_t n, size_t m )
+{
+    void *p = g10_malloc_secure( n*m );
+    if( p )
+       memset( p, 0, n*m );
+    return p;
+}
+
+
+void *
+g10_xmalloc( size_t n )
+{
+    void *p = g10_malloc( n );
+    if( !n ) {
+       fprintf(stderr,"OUT OF CORE\n");
+       exit(4);
+    }
+    return p;
+}
+
+void *
+g10_xmalloc_secure( size_t n )
+{
+    void *p = g10_malloc_secure( n );
+    if( !n ) {
+       fprintf(stderr,"OUT OF CORE in secure memory\n");
+       exit(4);
+    }
+    return p;
+}
+
+void *
+g10_xcalloc( size_t n, size_t m )
+{
+    void *p = g10_calloc( n, m );
+    if( !n ) {
+       fprintf(stderr,"OUT OF CORE\n");
+       exit(4);
+    }
+    return p;
+}
+
+void *
+g10_xcalloc_secure( size_t n, size_t m )
+{
+    void *p = g10_calloc_secure( n, m );
+    if( !n ) {
+       fprintf(stderr,"OUT OF CORE in secure memory\n");
+       exit(4);
+    }
+    return p;
+}
 
index ac2b0f3..32f12ac 100644 (file)
@@ -132,14 +132,24 @@ dump_sexp( NODE node )
 }
 
 
+void
+gcry_sexp_dump( GCRY_SEXP a )
+{
+    do_dump_list( a, 0 );
+}
+
+
 /****************
  * Create a new SEXP element (data)
+ * If length is 0 it is assumed that buffer is a C string.
  */
 GCRY_SEXP
 gcry_sexp_new_data( const char *buffer, size_t length )
 {
     NODE list, node;
 
+    if( !length )
+       length = strlen(buffer);
     node = m_alloc_clear( sizeof *node + length );
     node->type = ntDATA;
     node->u.data.len = length;
@@ -151,20 +161,60 @@ gcry_sexp_new_data( const char *buffer, size_t length )
 }
 
 /****************
+ * Create a new SEXP element (mpi)
+ */
+GCRY_SEXP
+gcry_sexp_new_mpi( GCRY_MPI mpi )
+{
+    NODE list, node;
+
+    node = m_alloc_clear( sizeof *node );
+    node->type = ntMPI;
+    node->u.mpi = gcry_mpi_copy( mpi );
+    list = m_alloc_clear( sizeof *list );
+    list->type = ntLIST;
+    list->u.list = node;
+    return list;
+}
+
+
+/****************
+ * Create a pair of a name and some arbitrary data.
+ */
+GCRY_SEXP
+gcry_sexp_new_name_data( const char *name, const char *buffer, size_t length )
+{
+    return gcry_sexp_cons( gcry_sexp_new_data( name, 0 ),
+                          gcry_sexp_new_data( buffer, length ) );
+}
+
+/****************
+ * Create a pair of a name and a MPI
+ */
+GCRY_SEXP
+gcry_sexp_new_name_mpi( const char *name, GCRY_MPI mpi )
+{
+    return gcry_sexp_cons( gcry_sexp_new_data( name, 0 ),
+                          gcry_sexp_new_mpi( mpi ) );
+}
+
+
+/****************
  * Release resource of the given SEXP object.
  */
 void
 gcry_sexp_release( GCRY_SEXP sexp )
 {
+    /* FIXME! */
 }
 
 
 
 
 /****************
- * Make a pair from lists a and b, don't use a or b alter on.
+ * Make a pair from lists a and b, don't use a or b later on.
  * Special behaviour:  If one is a single element list we put the
- * element straingt into the new pair.
+ * element straight into the new pair.
  */
 GCRY_SEXP
 gcry_sexp_cons( GCRY_SEXP a, GCRY_SEXP b )
@@ -202,9 +252,10 @@ gcry_sexp_cons( GCRY_SEXP a, GCRY_SEXP b )
     return head;
 }
 
+
 /****************
  * Make a list from all items, the end of list is indicated by a NULL
- * don´ use the passed lists lateron, they are void.
+ * don't use the passed lists later on, they are void.
  */
 GCRY_SEXP
 gcry_sexp_vlist( GCRY_SEXP a, ... )
@@ -248,6 +299,43 @@ gcry_sexp_vlist( GCRY_SEXP a, ... )
 }
 
 
+/****************
+ * Append n to the list a
+ * Don't use n later on.
+ * Returns: a new ist (which maybe a)
+ */
+GCRY_SEXP
+gcry_sexp_append( GCRY_SEXP a, GCRY_SEXP n )
+{
+
+    GCRY_SEXP node;
+
+    if( a->type != ntLIST ) {
+       fputs("sexp_append: a is not a list\n", stderr );
+       return a;
+    }
+
+    if( n->type != ntLIST ) {
+       fputs("sexp_append: n is not a list\n", stderr );
+       return a;
+    }
+
+    for( node = a; node->next; node = node->next )
+       ;
+
+    node->next = n;
+    return a;
+}
+
+GCRY_SEXP
+gcry_sexp_prepend( GCRY_SEXP a, GCRY_SEXP n )
+{
+
+    fputs("sexp_prepend: not impl.\n", stderr );
+    return a;
+}
+
+
 
 /****************
  * Locate data in a list. Data must be the first item in the list.
@@ -346,6 +434,8 @@ gcry_sexp_car( GCRY_SEXP list )
 const char *
 gcry_sexp_car_data( GCRY_SEXP list, size_t *datalen )
 {
+    if( list && list->type == ntLIST && !list->next )
+       list = list->u.list;
     if( list && list->type == ntDATA ) {
        *datalen = list->u.data.len;
        return list->u.data.d;
@@ -355,6 +445,27 @@ gcry_sexp_car_data( GCRY_SEXP list, size_t *datalen )
 }
 
 /****************
+ * Get a MPI from the car
+ */
+GCRY_MPI
+gcry_sexp_car_mpi( GCRY_SEXP list, int mpifmt )
+{
+    if( list && list->type == ntLIST && !list->next )
+       list = list->u.list;
+    if( mpifmt && list->type == ntDATA ) {
+       MPI a;
+       size_t n = list->u.data.len;
+       if( gcry_mpi_scan( &a, mpifmt, list->u.data.d, &n ) )
+           return NULL;
+       return a;
+    }
+    else if( list->type == ntMPI )
+       return gcry_mpi_copy( list->u.mpi );
+
+    return NULL;
+}
+
+/****************
  * Get the CDR
  */
 GCRY_SEXP
@@ -386,14 +497,14 @@ gcry_sexp_cdr_data( GCRY_SEXP list, size_t *datalen )
  * Actually this funtion returns only the second item of the list
  * and ignores any further arguments.
  */
-MPI
+GCRY_MPI
 gcry_sexp_cdr_mpi( GCRY_SEXP list, int mpifmt )
 {
     NODE node = list;
 
     if( !node || !(node = node->next) || node == ntLIST )
        return NULL;
-    if( node->type == ntDATA ) {
+    if( mpifmt && node->type == ntDATA ) {
        MPI a;
        size_t n = node->u.data.len;
        if( gcry_mpi_scan( &a, mpifmt, node->u.data.d, &n ) )
@@ -408,22 +519,6 @@ gcry_sexp_cdr_mpi( GCRY_SEXP list, int mpifmt )
 
 
 /****************
- * Check wether the car is equal to data
- */
-#if 0 /* not tested */
-int
-gcry_sexp_eqp_car( GCRY_SEXP list, const char *data, size_t datalen )
-{
-    if( list && list->type == ntDATA
-       && list->u.data.len == datalen
-       && !memcmp( list->u.data.d, list, listlen ) )
-       return 1;
-
-    return 0;
-}
-#endif
-
-/****************
  * Scan the provided buffer and return the S expression in our internal
  * format.  Returns a newly allocated expression.  If erroff is not NULL and
  * a parsing error has occured, the offset into buffer will be returned.
@@ -632,7 +727,7 @@ gcry_sexp_sscan( GCRY_SEXP *retsexp, const char *buffer,
            /* fixme: handle rescanning:
             * we can do this by saving our current state
             * and start over at p+1 -- Hmmm. At this point here
-            * we are in a well defined state, so we don´ need to save
+            * we are in a well defined state, so we don't need to save
             * it.  Great.
             */
            *erroff = p - buffer;
@@ -667,6 +762,9 @@ gcry_sexp_sprint( GCRY_SEXP sexp, int mode, char *buffer, size_t maxlength )
 
 
 
+
+
+#if 0
 /***********************************************************/
 
 const char *
@@ -675,6 +773,88 @@ strusage( int level )
     return default_strusage(level);
 }
 
+
+static int
+sexp_to_pk( GCRY_SEXP sexp, int want_private, MPI **retarray, int *retalgo)
+{
+    GCRY_SEXP list, l2;
+    const char *name;
+    const char *s;
+    size_t n;
+    int i, idx;
+    int algo;
+    const char *elems1, *elems2;
+    GCRY_MPI *array;
+    static struct { const char* name; int algo;
+                   const char* common_elements;
+                   const char* public_elements;
+                   const char* secret_elements;
+                 } algos[] = {
+       {  "dsa"            , PUBKEY_ALGO_DSA       , "pqgy", "", "x"    },
+       {  "rsa"            , PUBKEY_ALGO_RSA       , "ne",   "", "dpqu" },
+       {  "openpgp-dsa"    , PUBKEY_ALGO_DSA       , "pqgy", "", "x"    },
+       {  "openpgp-rsa"    , PUBKEY_ALGO_RSA       , "pqgy", "", "x"    },
+       {  "openpgp-elg"    , PUBKEY_ALGO_ELGAMAL_E , "pgy",  "", "x"    },
+       {  "openpgp-elg-sig", PUBKEY_ALGO_ELGAMAL   , "pgy",  "", "x"    },
+       {  NULL }};
+
+    /* check that the first element is valid */
+    list = gcry_sexp_find_token( sexp, want_private? "private-key"
+                                                   :"public-key", 0 );
+    if( !list )
+       return -1; /* Does not contain a public- or private-key object */
+    list = gcry_sexp_cdr( list );
+    if( !list )
+       return -2; /* no cdr for the key object */
+    name = gcry_sexp_car_data( list, &n );
+    if( !name )
+       return -3; /* invalid structure of object */
+    fprintf(stderr, "algorithm name: `%.*s'\n", (int)n, name );
+    for(i=0; (s=algos[i].name); i++ ) {
+       if( strlen(s) == n && !memcmp( s, name, n ) )
+           break;
+    }
+    if( !s )
+       return -4; /* unknown algorithm */
+    algo = algos[i].algo;
+    elems1 = algos[i].common_elements;
+    elems2 = want_private? algos[i].secret_elements : algos[i].public_elements;
+    array = m_lib_alloc_clear( (strlen(elems1)+strlen(elems2)+1) * sizeof *array );
+    idx = 0;
+    for(s=elems1; *s; s++, idx++ ) {
+       l2 = gcry_sexp_find_token( list, s, 1 );
+       if( !l2 ) {
+           m_lib_free( array );
+           return -5; /* required parameter not found */
+       }
+       array[idx] = gcry_sexp_cdr_mpi( l2, GCRYMPI_FMT_USG );
+       if( !array[idx] ) {
+           m_lib_free( array );
+           return -6; /* required parameter is invalid */
+       }
+    }
+    for(s=elems2; *s; s++, idx++ ) {
+       l2 = gcry_sexp_find_token( list, s, 1 );
+       if( !l2 ) {
+           m_lib_free( array );
+           return -5; /* required parameter not found */
+       }
+       /* FIXME: put the MPI in secure memory when needed */
+       array[idx] = gcry_sexp_cdr_mpi( l2, GCRYMPI_FMT_USG );
+       if( !array[idx] ) {
+           m_lib_free( array );
+           return -6; /* required parameter is invalid */
+       }
+    }
+
+    *retarray = array;
+    *retalgo = algo;
+
+    return 0;
+}
+
+
+
 int
 main(int argc, char **argv)
 {
@@ -682,7 +862,7 @@ main(int argc, char **argv)
     size_t erroff;
     int rc, n;
     FILE *fp;
-    GCRY_SEXP s_pk, s_dsa, s_p, s_q, s_g, sexp;
+    GCRY_SEXP s_pk, s_dsa, s_p, s_q, s_g, s_y, sexp;
 
   #if 0
     fp = stdin;
@@ -692,15 +872,22 @@ main(int argc, char **argv)
        fprintf(stderr, "parse error %d at offset %u\n", rc, erroff );
        exit(1);
     }
+    fputs("We have this S-Exp:\n",stderr);
+    dump_sexp( sexp );
   #else
     s_pk = SEXP_NEW( "public-key", 10 );
     fputs("pk:\n",stderr);dump_sexp( s_pk );
     s_dsa = SEXP_NEW( "dsa", 3 );
     s_p = SEXP_CONS( SEXP_NEW( "p", 1 ), SEXP_NEW( "PPPPPP", 6 ) );
     fputs("p:\n",stderr);dump_sexp( s_p );
-    s_q = SEXP_CONS( SEXP_NEW( "q", 1 ), SEXP_NEW( "QQQ", 3 ) );
-    s_g = SEXP_CONS( SEXP_NEW( "g", 1 ), SEXP_NEW( "GGGGGG", 6 ) );
+    s_y = SEXP_CONS( SEXP_NEW( "y", 1 ), SEXP_NEW( "YYYYYYYY", 8 ) );
+    fputs("y:\n",stderr);dump_sexp( s_y );
+    s_q = gcry_sexp_new_name_data( "q", "QQQ", 3 );
+    fputs("q:\n",stderr);dump_sexp( s_q );
+    s_g = gcry_sexp_new_name_mpi( "g" , gcry_mpi_set_ui(NULL, 42) );
+    fputs("g:\n",stderr);dump_sexp( s_g );
     sexp = SEXP_CONS( s_pk, gcry_sexp_vlist( s_dsa,
+                                            s_y,
                                             s_p,
                                             s_q,
                                             s_g,
@@ -725,9 +912,26 @@ main(int argc, char **argv)
            dump_sexp( s1 );
          }
 
+       #if 1
+       {  int i,rc, algo;
+          GCRY_MPI *array;
+
+          rc = sexp_to_pk( s1, 0, &array, &algo);
+          if( rc )
+             fprintf(stderr, "sexp_to_pk failed: rc=%d\n", rc );
+          else {
+              for(i=0; array[i]; i++ ) {
+                  fprintf(stderr, "MPI[%d]: ", i);
+                  dump_mpi( array[i] );
+                  fprintf(stderr, "\n");
+              }
+           }
+       }
+       #endif
+
 
        if( argc > 2 ) /* get the MPI out of the list */
-       #if 1
+       #if 0
          {
            GCRY_SEXP s2;
            const char *p;
@@ -758,17 +962,45 @@ main(int argc, char **argv)
 
 
          }
-       #elif 0
+       #elif 1
          {
            GCRY_SEXP s2;
            MPI a;
+           const char *p;
+           size_t n;
+
+           fprintf(stderr,"*********************************\n");
+           p = gcry_sexp_car_data( s1, &n );
+           if( !p ) {
+               fputs("no CAR\n", stderr );
+               exit(1);
+           }
+           fprintf(stderr, "CAR=`%.*s'\n", (int)n, p );
+           s2 = gcry_sexp_cdr( s1 );
+           if( !s2 ) {
+               fputs("no CDR\n", stderr );
+               exit(1);
+
+           }
+           p = gcry_sexp_car_data( s2, &n );
+           if( !p ) {
+               fputs("no data at CAR\n", stderr );
+               exit(1);
+           }
+           fprintf(stderr, "CAR=`%.*s'\n", (int)n, p );
 
            s2 = gcry_sexp_find_token( s1, argv[2], strlen(argv[2]) );
-           if( !s1 )
+           if( !s2 )
            {
               fprintf(stderr, "didn't found `%s'\n", argv[2] );
               exit(1);
            }
+           p = gcry_sexp_car_data( s2, &n );
+           if( !p ) {
+               fputs("no CAR\n", stderr );
+               exit(1);
+           }
+           fprintf(stderr, "CAR=`%.*s'\n", (int)n, p );
 
            a = gcry_sexp_cdr_mpi( s2, GCRYMPI_FMT_USG );
            if( a ) {
@@ -806,4 +1038,4 @@ main(int argc, char **argv)
       }
     return 0;
 }
-
+#endif