ElGamal funktioniert und ist default
authorWerner Koch <wk@gnupg.org>
Mon, 24 Nov 1997 22:24:04 +0000 (22:24 +0000)
committerWerner Koch <wk@gnupg.org>
Mon, 24 Nov 1997 22:24:04 +0000 (22:24 +0000)
31 files changed:
cipher/elgamal.c
cipher/elgamal.h
cipher/primegen.c
cipher/rsa.c
doc/DETAILS [new file with mode: 0644]
g10/Makefile.am
g10/Makefile.in
g10/build-packet.c
g10/checksig.c [deleted file]
g10/encode.c
g10/free-packet.c
g10/g10.c
g10/getkey.c
g10/keydb.h
g10/keygen.c
g10/keyid.c [new file with mode: 0644]
g10/main.h
g10/mainproc.c
g10/packet.h
g10/parse-packet.c
g10/pubkey-enc.c
g10/seckey-cert.c
g10/seskey.c
g10/sig-check.c
include/cipher.h
include/mpi.h
mpi/mpi-add.c
mpi/mpi-inv.c
mpi/mpi-mul.c
tools/mpicalc.c
util/logger.c

index 305e1db..b123973 100644 (file)
 #include <string.h>
 #include "util.h"
 #include "mpi.h"
+#include "cipher.h"
 #include "elgamal.h"
 
 
+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;
+}
+
+
+static void
+test_keys( ELG_public_key *pk, ELG_secret_key *sk, unsigned nbits )
+{
+    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 );
+
+    mpi_set_bytes( test, nbits, get_random_byte, 0 );
+
+    elg_encipher( out1_a, out1_b, test, pk );
+    elg_decipher( out2, out1_a, out1_b, sk );
+    if( mpi_cmp( test, out2 ) )
+       log_fatal("ElGamal operation: encipher, decipher failed\n");
+
+    elg_sign( out1_a, out1_b, test, sk );
+    if( !elg_verify( out1_a, out1_b, test, pk ) )
+       log_fatal("ElGamal operation: sign, verify failed\n");
+
+    mpi_free( test );
+    mpi_free( out1_a );
+    mpi_free( out1_b );
+    mpi_free( out2 );
+}
+
+
 /****************
- * Public key operation. Encrypt INPUT with PKEY and put result into OUTPUT.
- *
- *
- *
- * Where c is OUTPUT, m is INPUT and e,n are elements of PKEY.
+ * generate a random secret exponent k from prime p, so
+ * that k is relatively prime to p-1
+ */
+static MPI
+gen_k( MPI p )
+{
+    MPI k = mpi_alloc_secure( mpi_get_nlimbs(p) );
+    MPI temp = mpi_alloc( mpi_get_nlimbs(p) );
+    MPI p_1 = mpi_copy(p);
+    unsigned nbits = mpi_get_nbits(p);
+
+    if( DBG_CIPHER )
+       log_debug("choosing a random k ");
+    mpi_sub_ui( p_1, p, 1);
+    for(;;) {
+       if( DBG_CIPHER )
+           fputc('.', stderr);
+       mpi_set_bytes( k, nbits, get_random_byte, 1 );
+       mpi_set_bit( k, nbits-1 ); /* make sure it's high (needed?) */
+       if( mpi_cmp( k, p_1 ) >= 0 )
+           continue; /* is not smaller than (p-1) */
+       if( mpi_gcd( temp, k, p_1 ) )
+           break;  /* okay, k is relatively prime to (p-1) */
+    }
+    if( DBG_CIPHER )
+       fputc('\n', stderr);
+    mpi_free(p_1);
+    mpi_free(temp);
+
+    return k;
+}
+
+/****************
+ * Generate a key pair with a key of size NBITS
+ * Returns: 2 structures filles with all needed values
  */
 void
-elg_public(MPI output, MPI input, ELG_public_key *pkey )
+elg_generate( ELG_public_key *pk, ELG_secret_key *sk, unsigned nbits )
 {
+    MPI p;    /* the prime */
+    MPI g;
+    MPI x;    /* the secret exponent */
+    MPI y;
 
+    p = generate_public_prime( nbits );
+    /* FIXME: check wether we shall assert that (p-1)/2 is also prime
+     *       Schneier votes against it
+     */
+    g = mpi_alloc_set_ui(3);
+
+    /* select a random number */
+    x = mpi_alloc_secure( nbits/BITS_PER_MPI_LIMB );
+    if( DBG_CIPHER )
+       log_debug("choosing a random x ");
+    do {
+       if( DBG_CIPHER )
+           fputc('.', stderr);
+       mpi_set_bytes( x, nbits, get_random_byte, 1 ); /* fixme: should be 2 */
+       mpi_set_bit( x, nbits-1 ); /* make sure it's high (needed?) */
+    } while( mpi_cmp( x, p ) >= 0 );  /* x must be samller than p */
+
+    y = mpi_alloc(nbits/BITS_PER_MPI_LIMB);
+    mpi_powm( y, g, x, p );
+
+    if( DBG_CIPHER ) {
+       fputc('\n', stderr);
+       log_mpidump("elg  p= ", p );
+       log_mpidump("elg  g= ", g );
+       log_mpidump("elg  y= ", y );
+       log_mpidump("elg  x= ", x );
+    }
+
+
+    /* 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 );
 }
 
+
 /****************
- * Secret key operation. Encrypt INPUT with SKEY and put result into OUTPUT.
- *
- *
- *
- * Where m is OUTPUT, c is INPUT and d,n are elements of PKEY.
+ * Test wether the secret key is valid.
+ * Returns: if this is a valid key.
+ */
+int
+elg_check_secret_key( ELG_secret_key *sk )
+{
+    int rc;
+    MPI y = mpi_alloc( mpi_get_nlimbs(sk->y) );
+
+    mpi_powm( y, sk->g, sk->x, sk->p );
+    rc = !mpi_cmp( y, sk->y );
+    mpi_free( y );
+    return rc;
+}
+
+
+void
+elg_encipher(MPI a, MPI b, MPI input, ELG_public_key *pkey )
+{
+    MPI k;
+
+    k = gen_k( pkey->p );
+    mpi_powm( a, pkey->g, k, pkey->p );
+    /* b = (y^k * input) mod p
+     *  = ((y^k mod p) * (input mod p)) mod p
+     * and because input is < p  (FIXME: check this!)
+     *  = ((y^k mod p) * input) mod p
+     */
+    mpi_powm( b, pkey->y, k, pkey->p );
+    mpi_mulm( b, b, input, pkey->p );
+  #if 0
+    if( DBG_CIPHER ) {
+       log_mpidump("elg encipher y= ", pkey->y);
+       log_mpidump("elg encipher p= ", pkey->p);
+       log_mpidump("elg encipher k= ", k);
+       log_mpidump("elg encipher M= ", input);
+       log_mpidump("elg encipher a= ", a);
+       log_mpidump("elg encipher b= ", b);
+    }
+  #endif
+    mpi_free(k);
+}
+
+
+
+
+void
+elg_decipher(MPI output, MPI a, MPI b, ELG_secret_key *skey )
+{
+    MPI t1 = mpi_alloc_secure( mpi_get_nlimbs( skey->p ) );
+
+    /* output = b/(a^x) mod p */
+
+    mpi_powm( t1, a, skey->x, skey->p );
+    mpi_invm( t1, t1, skey->p );
+    mpi_mulm( output, b, t1, skey->p );
+  #if 0
+    if( DBG_CIPHER ) {
+       log_mpidump("elg decipher x= ", skey->x);
+       log_mpidump("elg decipher p= ", skey->p);
+       log_mpidump("elg decipher a= ", a);
+       log_mpidump("elg decipher b= ", b);
+       log_mpidump("elg decipher M= ", output);
+    }
+  #endif
+    mpi_free(t1);
+}
+
+
+/****************
+ * Make an Elgamal signature out of INPUT
  */
+
 void
-elg_secret(MPI output, MPI input, ELG_secret_key *skey )
+elg_sign(MPI a, MPI b, MPI input, ELG_secret_key *skey )
 {
+    MPI k;
+    MPI t   = mpi_alloc( mpi_get_nlimbs(a) );
+    MPI inv = mpi_alloc( mpi_get_nlimbs(a) );
+    MPI p_1 = mpi_copy(skey->p);
+
+   /*
+    * b = (t * inv) mod (p-1)
+    * b = (t * inv(k,(p-1),(p-1)) mod (p-1)
+    * b = (((M-x*a) mod (p-1)) * inv(k,(p-1),(p-1))) mod (p-1)
+    *
+    */
+    mpi_sub_ui(p_1, p_1, 1);
+    k = gen_k( skey->p );
+    mpi_powm( a, skey->g, k, skey->p );
+    mpi_mul(t, skey->x, a );
+    mpi_subm(t, input, t, p_1 );
+    while( mpi_is_neg(t) )
+       mpi_add(t, t, p_1);
+    mpi_invm(inv, k, p_1 );
+    mpi_mulm(b, t, inv, p_1 );
 
+  #if 0
+    if( DBG_CIPHER ) {
+       log_mpidump("elg sign p= ", skey->p);
+       log_mpidump("elg sign g= ", skey->g);
+       log_mpidump("elg sign y= ", skey->y);
+       log_mpidump("elg sign x= ", skey->x);
+       log_mpidump("elg sign k= ", k);
+       log_mpidump("elg sign M= ", input);
+       log_mpidump("elg sign a= ", a);
+       log_mpidump("elg sign b= ", b);
+    }
+  #endif
+    mpi_free(k);
+    mpi_free(t);
+    mpi_free(inv);
+    mpi_free(p_1);
 }
 
 
+/****************
+ * Returns true if the signature composed from A and B is valid.
+ */
+int
+elg_verify(MPI a, MPI b, MPI input, ELG_public_key *pkey )
+{
+    int rc;
+    MPI t1 = mpi_alloc( mpi_get_nlimbs(a) );
+    MPI t2 = mpi_alloc( mpi_get_nlimbs(a) );
+
+    mpi_powm( t1, pkey->y, a, pkey->p );
+    mpi_powm( t2, a, b, pkey->p );
+    mpi_mulm( t1, t1, t2, pkey->p );
+
+    mpi_powm( t2, pkey->g, input, pkey->p );
+
+    rc = !mpi_cmp( t1, t2 );
+
+    mpi_free(t1);
+    mpi_free(t2);
+    return rc;
+}
 
index 3b63175..e93b49e 100644 (file)
 #include "mpi.h"
 
 typedef struct {
-    MPI e;         /* exponent */
-    MPI n;         /* modulus */
+    MPI p;         /* prime */
+    MPI g;         /* group generator */
+    MPI y;         /* g^x mod p */
 } ELG_public_key;
 
 
 typedef struct {
-    MPI e;         /* public exponent */
-    MPI n;         /* public modulus */
-    MPI p;         /* prime  p. */
-    MPI q;         /* prime  q. */
-    MPI d;         /* exponent */
-    MPI u;         /* inverse of p mod q. */
+    MPI p;         /* prime */
+    MPI g;         /* group generator */
+    MPI y;         /* g^x mod p */
+    MPI x;         /* secret exponent */
 } ELG_secret_key;
 
 
-void elg_public(MPI output, MPI input, ELG_public_key *skey );
-void elg_secret(MPI output, MPI input, ELG_secret_key *skey );
-
+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 );
+int  elg_check_secret_key( ELG_secret_key *sk );
+void elg_encipher(MPI a, MPI b, MPI input, ELG_public_key *pkey );
+void elg_decipher(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*/
index 07d83d8..0173b3d 100644 (file)
 
 static int no_of_small_prime_numbers;
 static int rabin_miller( MPI n );
+static MPI gen_prime( unsigned nbits, int mode );
 
 
 /****************
  * Generate a prime number (stored in secure memory)
  */
 MPI
-generate_random_prime( unsigned  nbits )
+generate_secret_prime( unsigned  nbits )
+{
+    return gen_prime( nbits, 1 );
+}
+
+MPI
+generate_public_prime( unsigned  nbits )
+{
+    return gen_prime( nbits, 0 );
+}
+
+static MPI
+gen_prime( unsigned  nbits, int secret )
 {
 
     unsigned  nlimbs;
@@ -61,7 +74,7 @@ generate_random_prime( unsigned  nbits )
     val_3  = mpi_alloc( nlimbs );
     mpi_set_ui(val_3, 3);
     result = mpi_alloc( nlimbs );
-    prime  = mpi_alloc_secure( nlimbs );
+    prime  = secret? mpi_alloc_secure( nlimbs ): mpi_alloc( nlimbs );
     count1 = count2 = 0;
     /* enter (endless) loop */
     for(;;) {
index b2694ed..a1f0845 100644 (file)
@@ -95,8 +95,8 @@ rsa_generate( RSA_public_key *pk, RSA_secret_key *sk, unsigned nbits )
     MPI f;
 
     /* select two (very secret) primes */
-    p = generate_random_prime( nbits / 2 );
-    q = generate_random_prime( nbits / 2 );
+    p = generate_secret_prime( nbits / 2 );
+    q = generate_secret_prime( nbits / 2 );
     if( mpi_cmp( p, q ) > 0 ) /* p shall be smaller than q (for calc of u)*/
        mpi_swap(p,q);
     /* calculate Euler totient: phi = (p-1)(q-1) */
@@ -120,10 +120,10 @@ rsa_generate( RSA_public_key *pk, RSA_secret_key *sk, unsigned nbits )
        mpi_add_ui( e, e, 2);
     /* calculate the secret key d = e^1 mod phi */
     d = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
-    mpi_inv_mod(d, e, f );
+    mpi_invm(d, e, f );
     /* calculate the inverse of p and q (used for chinese remainder theorem)*/
     u = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
-    mpi_inv_mod(u, p, q );
+    mpi_invm(u, p, q );
 
     if( DBG_CIPHER ) {
        log_mpidump("  p= ", p );
diff --git a/doc/DETAILS b/doc/DETAILS
new file mode 100644 (file)
index 0000000..3b447c7
--- /dev/null
@@ -0,0 +1,7 @@
+
+
+    * For packet version 3 we calculate the keyids this way:
+       RSA     := low 64 bits of n
+       ELGAMAL := low 64 bits of y
+
+
index a8d13ea..bb0b965 100644 (file)
@@ -21,6 +21,7 @@ g10_SOURCES = g10.c           \
              cipher.c          \
              options.h         \
              openfile.c        \
+             keyid.c           \
              packet.h          \
              parse-packet.c    \
              passphrase.c      \
index d7b0855..651fdf2 100644 (file)
@@ -59,6 +59,7 @@ g10_SOURCES = g10.c           \
              cipher.c          \
              options.h         \
              openfile.c        \
+             keyid.c           \
              packet.h          \
              parse-packet.c    \
              passphrase.c      \
@@ -90,7 +91,7 @@ COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
 LINK = $(CC) $(LDFLAGS) -o $@
 g10_OBJECTS = g10.o build-packet.o compress.o encode.o encr-data.o \
 free-packet.o getkey.o keygen.o mainproc.o armor.o mdfilter.o cipher.o \
-openfile.o parse-packet.o passphrase.o plaintext.o pubkey-enc.o \
+openfile.o keyid.o parse-packet.o passphrase.o plaintext.o pubkey-enc.o \
 seckey-cert.o seskey.o sign.o comment.o sig-check.o
 EXTRA_g10_SOURCES =
 g10_LDADD = $(LDADD)
@@ -111,12 +112,12 @@ $(srcdir)/.deps/cipher.P $(srcdir)/.deps/comment.P \
 $(srcdir)/.deps/compress.P $(srcdir)/.deps/encode.P \
 $(srcdir)/.deps/encr-data.P $(srcdir)/.deps/free-packet.P \
 $(srcdir)/.deps/g10.P $(srcdir)/.deps/getkey.P $(srcdir)/.deps/keygen.P \
-$(srcdir)/.deps/mainproc.P $(srcdir)/.deps/mdfilter.P \
-$(srcdir)/.deps/openfile.P $(srcdir)/.deps/parse-packet.P \
-$(srcdir)/.deps/passphrase.P $(srcdir)/.deps/plaintext.P \
-$(srcdir)/.deps/pubkey-enc.P $(srcdir)/.deps/seckey-cert.P \
-$(srcdir)/.deps/seskey.P $(srcdir)/.deps/sig-check.P \
-$(srcdir)/.deps/sign.P
+$(srcdir)/.deps/keyid.P $(srcdir)/.deps/mainproc.P \
+$(srcdir)/.deps/mdfilter.P $(srcdir)/.deps/openfile.P \
+$(srcdir)/.deps/parse-packet.P $(srcdir)/.deps/passphrase.P \
+$(srcdir)/.deps/plaintext.P $(srcdir)/.deps/pubkey-enc.P \
+$(srcdir)/.deps/seckey-cert.P $(srcdir)/.deps/seskey.P \
+$(srcdir)/.deps/sig-check.P $(srcdir)/.deps/sign.P
 SOURCES = $(g10_SOURCES)
 OBJECTS = $(g10_OBJECTS)
 
index 5bda607..c0ddb9e 100644 (file)
@@ -163,7 +163,12 @@ do_pubkey_cert( IOBUF out, int ctb, PKT_pubkey_cert *pkc )
     write_32(a, pkc->timestamp );
     write_16(a, pkc->valid_days );
     iobuf_put(a, pkc->pubkey_algo );
-    if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
+    if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
+       mpi_encode(a, pkc->d.elg.p );
+       mpi_encode(a, pkc->d.elg.g );
+       mpi_encode(a, pkc->d.elg.y );
+    }
+    else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
        mpi_encode(a, pkc->d.rsa.rsa_n );
        mpi_encode(a, pkc->d.rsa.rsa_e );
     }
@@ -191,7 +196,26 @@ do_seckey_cert( IOBUF out, int ctb, PKT_seckey_cert *skc )
     write_32(a, skc->timestamp );
     write_16(a, skc->valid_days );
     iobuf_put(a, skc->pubkey_algo );
-    if( skc->pubkey_algo == PUBKEY_ALGO_RSA ) {
+    if( skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
+       mpi_encode(a, skc->d.elg.p );
+       mpi_encode(a, skc->d.elg.g );
+       mpi_encode(a, skc->d.elg.y );
+       iobuf_put(a, skc->d.elg.protect_algo );
+       skc->d.elg.calc_csum = 0;
+       if( skc->d.elg.protect_algo ) {
+           assert( skc->d.elg.is_protected == 1 );
+           assert( skc->d.elg.protect_algo == CIPHER_ALGO_BLOWFISH );
+           iobuf_write(a, skc->d.elg.protect.blowfish.iv, 8 );
+           mpi_write_csum(a, (byte*)skc->d.elg.x, &skc->d.elg.calc_csum );
+       }
+       else {  /* not protected */
+           assert( !skc->d.elg.is_protected );
+           mpi_encode_csum(a, skc->d.elg.x, &skc->d.elg.calc_csum );
+       }
+
+       write_16(a, skc->d.elg.calc_csum );
+    }
+    else if( skc->pubkey_algo == PUBKEY_ALGO_RSA ) {
        mpi_encode(a, skc->d.rsa.rsa_n );
        mpi_encode(a, skc->d.rsa.rsa_e );
        iobuf_put(a, skc->d.rsa.protect_algo );
@@ -240,7 +264,11 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
     write_32(a, enc->keyid[0] );
     write_32(a, enc->keyid[1] );
     iobuf_put(a,enc->pubkey_algo );
-    if( enc->pubkey_algo == PUBKEY_ALGO_RSA ) {
+    if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
+       mpi_encode(a, enc->d.elg.a );
+       mpi_encode(a, enc->d.elg.b );
+    }
+    else if( enc->pubkey_algo == PUBKEY_ALGO_RSA ) {
        mpi_encode(a, enc->d.rsa.rsa_integer );
     }
     else {
@@ -342,7 +370,14 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig )
     write_32(a, sig->keyid[0] );
     write_32(a, sig->keyid[1] );
     iobuf_put(a, sig->pubkey_algo );
-    if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) {
+    if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
+       iobuf_put(a, sig->d.elg.digest_algo );
+       iobuf_put(a, sig->d.elg.digest_start[0] );
+       iobuf_put(a, sig->d.elg.digest_start[1] );
+       mpi_encode(a, sig->d.elg.a );
+       mpi_encode(a, sig->d.elg.b );
+    }
+    else if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) {
        iobuf_put(a, sig->d.rsa.digest_algo );
        iobuf_put(a, sig->d.rsa.digest_start[0] );
        iobuf_put(a, sig->d.rsa.digest_start[1] );
diff --git a/g10/checksig.c b/g10/checksig.c
deleted file mode 100644 (file)
index 7f00d58..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/* checksig.c - check a signature
- *     Copyright (c) 1997 by Werner Koch (dd9jn)
- *
- * This file is part of G10.
- *
- * G10 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.
- *
- * G10 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 "packet.h"
-#include "iobuf.h"
-#include "memory.h"
-#include "util.h"
-#include "cipher.h"
-
-static void
-usage(void)
-{
-    fprintf(stderr, "usage: checksig textfile sigfile\n");
-    exit(1);
-}
-
-
-int
-main(int argc, char **argv)
-{
-    IOBUF a;
-    PACKET pkt;
-    PKT_signature *sig;
-    int rc, result, c;
-    FILE *fp;
-    MD5HANDLE md5;
-
-    if( argc != 3 )
-       usage();
-    argc--; argv++;
-
-
-    if( !(a = iobuf_open(argv[1])) )
-       log_fatal("can't open '%s'\n", argv[1]);
-
-    init_packet(&pkt);
-    while( (rc=parse_packet(a, &pkt)) != -1 ) {
-       if( !rc && pkt.pkttype == PKT_SECKEY_ENC ) {
-           sig = pkt.pkt.signature;
-           printf("sig: keyid=%08lX%08lX: ", sig->keyid[0], sig->keyid[1] );
-           if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) {
-               if( sig->d.rsa.digest_algo == DIGEST_ALGO_MD5 ) {
-                   if( !(fp = fopen(*argv, "rb")) )
-                       log_fatal("can't open '%s'\n", *argv);
-                   md5 = md5_open(0);
-                   while( (c=getc(fp)) != EOF )
-                       md5_putchar(md5, c );
-                   fclose(fp);
-                   result = md5_signature_check( sig, md5 );
-                   md5_close(md5);
-               }
-               else
-                   result = G10ERR_DIGEST_ALGO;
-           }
-           else
-               result = G10ERR_PUBKEY_ALGO;
-
-           if( !result )
-               fputs( "signature is good", stdout );
-           else if( result == G10ERR_DIGEST_ALGO )
-               printf( "Unknown digest algorithm %d", sig->d.rsa.digest_algo);
-           else if( result == G10ERR_PUBKEY_ALGO )
-               printf( "Unknown pubkey algorithm %d", sig->pubkey_algo);
-           else
-               fputs( g10_errstr(result), stdout);
-           putchar('\n');
-       }
-       free_packet(&pkt);
-    }
-
-    iobuf_close(a);
-    return 0;
-}
-
-
index 9ef2c10..eb4875d 100644 (file)
@@ -226,10 +226,35 @@ encode_crypt( const char *filename, STRLIST remusr )
        /* build the pubkey packet */
        enc = m_alloc_clear( sizeof *enc );
        enc->pubkey_algo = pkc->pubkey_algo;
-       if( enc->pubkey_algo == PUBKEY_ALGO_RSA ) {
+       if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
+           ELG_public_key pkey;
+           MPI frame;
+
+           enc->d.elg.a = mpi_alloc( mpi_get_nlimbs(pkc->d.elg.p) );
+           enc->d.elg.b = mpi_alloc( mpi_get_nlimbs(pkc->d.elg.p) );
+           keyid_from_pkc( pkc, enc->keyid );
+           frame = encode_session_key( cfx.dek, mpi_get_nbits(pkc->d.elg.p) );
+           pkey.p = pkc->d.elg.p;
+           pkey.g = pkc->d.elg.g;
+           pkey.y = pkc->d.elg.y;
+           if( DBG_CIPHER )
+               log_mpidump("Plain DEK frame: ", frame);
+           elg_encipher( enc->d.elg.a, enc->d.elg.b, frame, &pkey);
+           mpi_free( frame );
+           if( DBG_CIPHER ) {
+               log_mpidump("Encry DEK a: ", enc->d.elg.a );
+               log_mpidump("      DEK b: ", enc->d.elg.b );
+           }
+           if( opt.verbose ) {
+               ustr = get_user_id_string( enc->keyid );
+               log_info("ElGamal enciphered for: %s\n", ustr );
+               m_free(ustr);
+           }
+       }
+       else if( enc->pubkey_algo == PUBKEY_ALGO_RSA ) {
            RSA_public_key pkey;
 
-           mpi_get_keyid( pkc->d.rsa.rsa_n, enc->keyid );
+           keyid_from_pkc( pkc, enc->keyid );
            enc->d.rsa.rsa_integer = encode_session_key( cfx.dek,
                                        mpi_get_nbits(pkc->d.rsa.rsa_n) );
            pkey.n = pkc->d.rsa.rsa_n;
index 7d6eb4a..3103ee4 100644 (file)
 void
 free_pubkey_enc( PKT_pubkey_enc *enc )
 {
-    mpi_free( enc->d.rsa.rsa_integer );
+    if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
+       mpi_free( enc->d.elg.a );
+       mpi_free( enc->d.elg.b );
+    }
+    else if( enc->pubkey_algo == PUBKEY_ALGO_RSA )
+       mpi_free( enc->d.rsa.rsa_integer );
     m_free(enc);
 }
 
 void
 free_seckey_enc( PKT_signature *enc )
 {
-    mpi_free( enc->d.rsa.rsa_integer );
+    if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
+       mpi_free( enc->d.elg.a );
+       mpi_free( enc->d.elg.b );
+    }
+    else if( enc->pubkey_algo == PUBKEY_ALGO_RSA )
+       mpi_free( enc->d.rsa.rsa_integer );
     m_free(enc);
 }
 
 void
 free_pubkey_cert( PKT_pubkey_cert *cert )
 {
-    mpi_free( cert->d.rsa.rsa_n );
-    mpi_free( cert->d.rsa.rsa_e );
+    if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
+       mpi_free( cert->d.elg.p );
+       mpi_free( cert->d.elg.g );
+       mpi_free( cert->d.elg.y );
+    }
+    else if( cert->pubkey_algo == PUBKEY_ALGO_RSA ) {
+       mpi_free( cert->d.rsa.rsa_n );
+       mpi_free( cert->d.rsa.rsa_e );
+    }
     md5_close( cert->mfx.md5 );
     rmd160_close( cert->mfx.rmd160 );
     m_free(cert);
@@ -62,8 +79,15 @@ copy_pubkey_cert( PKT_pubkey_cert *d, PKT_pubkey_cert *s )
     if( !d )
        d = m_alloc(sizeof *d);
     memcpy( d, s, sizeof *d );
-    d->d.rsa.rsa_n = mpi_copy( s->d.rsa.rsa_n );
-    d->d.rsa.rsa_e = mpi_copy( s->d.rsa.rsa_e );
+    if( s->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
+       d->d.elg.p = mpi_copy( s->d.elg.p );
+       d->d.elg.g = mpi_copy( s->d.elg.g );
+       d->d.elg.y = mpi_copy( s->d.elg.y );
+    }
+    else if( s->pubkey_algo == PUBKEY_ALGO_RSA ) {
+       d->d.rsa.rsa_n = mpi_copy( s->d.rsa.rsa_n );
+       d->d.rsa.rsa_e = mpi_copy( s->d.rsa.rsa_e );
+    }
     d->mfx.md5 = NULL;
     d->mfx.rmd160 =NULL;
     return d;
@@ -72,19 +96,30 @@ copy_pubkey_cert( PKT_pubkey_cert *d, PKT_pubkey_cert *s )
 void
 free_seckey_cert( PKT_seckey_cert *cert )
 {
-    mpi_free( cert->d.rsa.rsa_n );
-    mpi_free( cert->d.rsa.rsa_e );
-    if( cert->d.rsa.is_protected ) {
-       m_free( cert->d.rsa.rsa_d );
-       m_free( cert->d.rsa.rsa_p );
-       m_free( cert->d.rsa.rsa_q );
-       m_free( cert->d.rsa.rsa_u );
+    if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
+       mpi_free( cert->d.elg.p );
+       mpi_free( cert->d.elg.g );
+       mpi_free( cert->d.elg.y );
+       if( cert->d.rsa.is_protected )
+           m_free( cert->d.elg.x );
+       else
+           mpi_free( cert->d.elg.x );
     }
-    else {
-       mpi_free( cert->d.rsa.rsa_d );
-       mpi_free( cert->d.rsa.rsa_p );
-       mpi_free( cert->d.rsa.rsa_q );
-       mpi_free( cert->d.rsa.rsa_u );
+    else if( cert->pubkey_algo == PUBKEY_ALGO_RSA ) {
+       mpi_free( cert->d.rsa.rsa_n );
+       mpi_free( cert->d.rsa.rsa_e );
+       if( cert->d.rsa.is_protected ) {
+           m_free( cert->d.rsa.rsa_d );
+           m_free( cert->d.rsa.rsa_p );
+           m_free( cert->d.rsa.rsa_q );
+           m_free( cert->d.rsa.rsa_u );
+       }
+       else {
+           mpi_free( cert->d.rsa.rsa_d );
+           mpi_free( cert->d.rsa.rsa_p );
+           mpi_free( cert->d.rsa.rsa_q );
+           mpi_free( cert->d.rsa.rsa_u );
+       }
     }
     m_free(cert);
 }
@@ -95,12 +130,20 @@ copy_seckey_cert( PKT_seckey_cert *d, PKT_seckey_cert *s )
     if( !d )
        d = m_alloc(sizeof *d);
     memcpy( d, s, sizeof *d );
-    d->d.rsa.rsa_n = mpi_copy( s->d.rsa.rsa_n );
-    d->d.rsa.rsa_e = mpi_copy( s->d.rsa.rsa_e );
-    d->d.rsa.rsa_d = mpi_copy( s->d.rsa.rsa_d );
-    d->d.rsa.rsa_p = mpi_copy( s->d.rsa.rsa_p );
-    d->d.rsa.rsa_q = mpi_copy( s->d.rsa.rsa_q );
-    d->d.rsa.rsa_u = mpi_copy( s->d.rsa.rsa_u );
+    if( s->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
+       d->d.elg.p = mpi_copy( s->d.elg.p );
+       d->d.elg.g = mpi_copy( s->d.elg.g );
+       d->d.elg.y = mpi_copy( s->d.elg.y );
+       d->d.elg.x = mpi_copy( s->d.elg.x );
+    }
+    else if( s->pubkey_algo == PUBKEY_ALGO_RSA ) {
+       d->d.rsa.rsa_n = mpi_copy( s->d.rsa.rsa_n );
+       d->d.rsa.rsa_e = mpi_copy( s->d.rsa.rsa_e );
+       d->d.rsa.rsa_d = mpi_copy( s->d.rsa.rsa_d );
+       d->d.rsa.rsa_p = mpi_copy( s->d.rsa.rsa_p );
+       d->d.rsa.rsa_q = mpi_copy( s->d.rsa.rsa_q );
+       d->d.rsa.rsa_u = mpi_copy( s->d.rsa.rsa_u );
+    }
     return d;
 }
 
index 496fda3..5235d0f 100644 (file)
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -220,7 +220,7 @@ main( int argc, char **argv )
       case aPrimegen:
        if( argc )
            usage(1);
-       mpi_print( stdout, generate_random_prime( pargs.r.ret_int ), 1);
+       mpi_print( stdout, generate_public_prime( pargs.r.ret_int ), 1);
        putchar('\n');
        break;
 
index 8ca4622..4aea8e7 100644 (file)
@@ -85,8 +85,9 @@ cache_pubkey_cert( PKT_pubkey_cert *pkc )
     pkc_cache_entry_t ce;
     u32 keyid[2];
 
-    if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
-       mpi_get_keyid( pkc->d.rsa.rsa_n, keyid );
+    if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL
+       || pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
+       keyid_from_pkc( pkc, keyid );
     }
     else
        return; /* don't know how to get the keyid */
@@ -252,13 +253,11 @@ get_pubkey_by_name( PKT_pubkey_cert *pkc, const char *name )
  * Get a secret key and store it into skey
  */
 int
-get_seckey( RSA_secret_key *skey, u32 *keyid )
+get_seckey( PKT_seckey_cert *skc, u32 *keyid )
 {
     int rc=0;
-    PKT_seckey_cert skc;
 
-    memset( &skc, 0, sizeof skc );
-    if( !(rc=scan_secret_keyring( &skc, keyid, NULL, "../keys/secring.g10" ) ) )
+    if( !(rc=scan_secret_keyring( skc, keyid, NULL, "../keys/secring.g10" ) ) )
        goto found;
     /* fixme: look at other places */
     goto leave;
@@ -267,22 +266,10 @@ get_seckey( RSA_secret_key *skey, u32 *keyid )
     /* get the secret key (this may prompt for a passprase to
      * unlock the secret key
      */
-    if( (rc = check_secret_key( &skc )) )
-       goto leave;
-    if( skc.pubkey_algo != PUBKEY_ALGO_RSA ) {
-       rc = G10ERR_PUBKEY_ALGO; /* unsupport algorithm */
+    if( (rc = check_secret_key( skc )) )
        goto leave;
-    }
-    /* copy the stuff to SKEY. skey is then the owner */
-    skey->e = skc.d.rsa.rsa_e;
-    skey->n = skc.d.rsa.rsa_n;
-    skey->p = skc.d.rsa.rsa_p;
-    skey->q = skc.d.rsa.rsa_q;
-    skey->d = skc.d.rsa.rsa_d;
-    skey->u = skc.d.rsa.rsa_u;
 
   leave:
-    memset( &skc, 0, sizeof skc );
     return rc;
 }
 
@@ -357,8 +344,9 @@ scan_keyring( PKT_pubkey_cert *pkc, u32 *keyid,
        }
        else if( keyid && pkt.pkttype == PKT_PUBKEY_CERT ) {
            switch( pkt.pkt.pubkey_cert->pubkey_algo ) {
+             case PUBKEY_ALGO_ELGAMAL:
              case PUBKEY_ALGO_RSA:
-               mpi_get_keyid( pkt.pkt.pubkey_cert->d.rsa.rsa_n , akeyid );
+               keyid_from_pkc( pkt.pkt.pubkey_cert, akeyid );
                if( akeyid[0] == keyid[0] && akeyid[1] == keyid[1] ) {
                    copy_pubkey_cert( pkc, pkt.pkt.pubkey_cert );
                    found++;
@@ -406,8 +394,9 @@ scan_keyring( PKT_pubkey_cert *pkc, u32 *keyid,
                log_error("Ooops: no pubkey for userid '%.*s'\n",
                            pkt.pkt.user_id->len, pkt.pkt.user_id->name);
            else {
-               if( last_pk->pubkey_algo == PUBKEY_ALGO_RSA ) {
-                    mpi_get_keyid( last_pk->d.rsa.rsa_n , akeyid );
+               if( last_pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL
+                   || last_pk->pubkey_algo == PUBKEY_ALGO_RSA ) {
+                    keyid_from_pkc( last_pk, akeyid );
                     cache_user_id( pkt.pkt.user_id, akeyid );
                }
                cache_pubkey_cert( last_pk );
@@ -462,8 +451,9 @@ scan_secret_keyring( PKT_seckey_cert *skc, u32 *keyid,
        }
        else if( keyid && pkt.pkttype == PKT_SECKEY_CERT ) {
            switch( pkt.pkt.seckey_cert->pubkey_algo ) {
+             case PUBKEY_ALGO_ELGAMAL:
              case PUBKEY_ALGO_RSA:
-               mpi_get_keyid( pkt.pkt.seckey_cert->d.rsa.rsa_n , akeyid );
+               keyid_from_skc( pkt.pkt.seckey_cert, akeyid );
                if( akeyid[0] == keyid[0] && akeyid[1] == keyid[1] ) {
                    copy_seckey_cert( skc, pkt.pkt.seckey_cert );
                    found++;
@@ -510,9 +500,10 @@ scan_secret_keyring( PKT_seckey_cert *skc, u32 *keyid,
                log_error("Ooops: no seckey for userid '%.*s'\n",
                            pkt.pkt.user_id->len, pkt.pkt.user_id->name);
            else {
-               if( last_pk->pubkey_algo == PUBKEY_ALGO_RSA ) {
-                    mpi_get_keyid( last_pk->d.rsa.rsa_n , akeyid );
-                    cache_user_id( pkt.pkt.user_id, akeyid );
+               if( last_pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL
+                  || last_pk->pubkey_algo == PUBKEY_ALGO_RSA ) {
+                   keyid_from_skc( last_pk, akeyid );
+                   cache_user_id( pkt.pkt.user_id, akeyid );
                }
            }
        }
index 62c6abe..ae3aeb8 100644 (file)
@@ -22,6 +22,7 @@
 #define G10_KEYDB_H
 
 #include "types.h"
+#include "packet.h"
 #include "cipher.h"
 
 
@@ -35,11 +36,13 @@ void cache_pubkey_cert( PKT_pubkey_cert *pkc );
 void cache_user_id( PKT_user_id *uid, u32 *keyid );
 int get_pubkey( PKT_pubkey_cert *pkc, u32 *keyid );
 int get_pubkey_by_name( PKT_pubkey_cert *pkc, const char *name );
-int get_seckey( RSA_secret_key *skey, u32 *keyid );
+int get_seckey( PKT_seckey_cert *skc, u32 *keyid );
 int get_seckey_by_name( PKT_seckey_cert *skc, const char *name );
 char*get_user_id_string( u32 *keyid );
 
-
+/*-- keyid.c --*/
+u32 keyid_from_skc( PKT_seckey_cert *skc, u32 *keyid );
+u32 keyid_from_pkc( PKT_pubkey_cert *pkc, u32 *keyid );
 
 
 
index 866824c..ff37159 100644 (file)
 #include "ttyio.h"
 #include "options.h"
 
+#if 0
+  #define TEST_ALGO  1
+  #define TEST_NBITS 256
+  #define TEST_UID   "Karl Test"
+#endif
+
+
 static int
 answer_is_yes( const char *s )
 {
@@ -62,6 +69,7 @@ write_uid( IOBUF out, const char *s )
 }
 
 
+#ifdef HAVE_RSA_CIPHER
 static int
 gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
 {
@@ -114,6 +122,61 @@ gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
     free_packet(&pkt2);
     return rc;
 }
+#endif /*HAVE_RSA_CIPHER*/
+
+static int
+gen_elg(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
+{
+    int rc;
+    PACKET pkt1, pkt2;
+    PKT_seckey_cert *skc;
+    PKT_pubkey_cert *pkc;
+    ELG_public_key pk;
+    ELG_secret_key sk;
+
+    elg_generate( &pk, &sk, nbits );
+
+    skc = m_alloc( sizeof *skc );
+    pkc = m_alloc( sizeof *pkc );
+    skc->timestamp = pkc->timestamp = make_timestamp();
+    skc->valid_days = pkc->valid_days = 0; /* fixme: make it configurable*/
+    skc->pubkey_algo = pkc->pubkey_algo = PUBKEY_ALGO_ELGAMAL;
+                      memset(&pkc->mfx, 0, sizeof pkc->mfx);
+                      pkc->d.elg.p = pk.p;
+                      pkc->d.elg.g = pk.g;
+                      pkc->d.elg.y = pk.y;
+    skc->d.elg.p = sk.p;
+    skc->d.elg.g = sk.g;
+    skc->d.elg.y = sk.y;
+    skc->d.elg.x = sk.x;
+
+    skc->d.elg.calc_csum = 0;
+    skc->d.elg.is_protected = 0; /* FIXME!!! */
+    skc->d.elg.protect_algo = 0; /* should be blowfish */
+    /*memcpy(skc->d.elg.protect.blowfish.iv,"12345678", 8);*/
+
+    init_packet(&pkt1);
+    pkt1.pkttype = PKT_PUBKEY_CERT;
+    pkt1.pkt.pubkey_cert = pkc;
+    init_packet(&pkt2);
+    pkt2.pkttype = PKT_SECKEY_CERT;
+    pkt2.pkt.seckey_cert = skc;
+
+    if( (rc = build_packet( pub_io, &pkt1 )) ) {
+       log_error("build pubkey_cert packet failed: %s\n", g10_errstr(rc) );
+       goto leave;
+    }
+    if( (rc = build_packet( sec_io, &pkt2 )) ) {
+       log_error("build seckey_cert packet failed: %s\n", g10_errstr(rc) );
+       goto leave;
+    }
+
+  leave:
+    free_packet(&pkt1);
+    free_packet(&pkt2);
+    return rc;
+}
+
 
 
 /****************
@@ -130,19 +193,62 @@ generate_keypair()
     IOBUF pub_io = NULL;
     IOBUF sec_io = NULL;
     int rc;
+    int algo;
+    const char *algo_name;
 
+  #ifndef TEST_ALGO
     if( opt.batch || opt.answer_yes || opt.answer_no )
        log_fatal("Key generation can only be used in interactive mode\n");
 
-    tty_printf("About to generate a new keypair:\n"
+    tty_printf("Please select the algorithm to use:\n"
+              "   (1) ElGamal is the suggested one.\n"
+          #ifdef HAVE_RSA_CIPHER
+              "   (2) RSA cannot be used inthe U.S.\n"
+          #endif
+              );
+  #endif
+
+    for(;;) {
+      #ifdef TEST_ALGO
+       algo = TEST_ALGO;
+      #else
+       answer = tty_get("Your selection? (1,2) ");
+       tty_kill_prompt();
+       algo = *answer? atoi(answer): 1;
+       m_free(answer);
+      #endif
+       if( algo == 1 ) {
+           algo = PUBKEY_ALGO_ELGAMAL;
+           algo_name = "ElGamal";
+           break;
+       }
+      #ifdef HAVE_RSA_CIPHER
+       else if( algo == 2 ) {
+           algo = PUBKEY_ALGO_RSA;
+           algo_name = "RSA";
+           break;
+       }
+      #endif
+    }
+
+
+
+    tty_printf("About to generate a new %s keypair.\n"
+         #ifndef TEST_NBITS
               "              minimum keysize is  768 bits\n"
               "              default keysize is 1024 bits\n"
-              "    highest suggested keysize is 2048 bits\n" );
+              "    highest suggested keysize is 2048 bits\n"
+         #endif
+                                                            , algo_name );
     for(;;) {
-       answer = tty_get("What keysize do you want? (256) ");
+      #ifdef TEST_NBITS
+       nbits = TEST_NBITS;
+      #else
+       answer = tty_get("What keysize do you want? (1024) ");
        tty_kill_prompt();
-       nbits = *answer? atoi(answer): 256;
+       nbits = *answer? atoi(answer): 1024;
        m_free(answer);
+      #endif
        if( nbits < 128 ) /* FIXME: change this to 768 */
            tty_printf("keysize too small; please select a larger one\n");
        else if( nbits > 2048 ) {
@@ -167,6 +273,11 @@ generate_keypair()
        nbits = ((nbits + 31) / 32) * 32;
        tty_printf("rounded up to %u bits\n", nbits );
     }
+
+  #ifdef TEST_UID
+    uid = m_alloc(strlen(TEST_UID)+1);
+    strcpy(uid, TEST_UID);
+  #else
     tty_printf( "\nYou need a User-ID to identify your key; please use your name and your\n"
                "email address in this suggested format:\n"
                "    \"Heinrich Heine <heinrichh@uni-duesseldorf.de>\n" );
@@ -189,6 +300,7 @@ generate_keypair()
            m_free(answer);
        }
     }
+  #endif
     /* now check wether we a are allowed to write the keyrings */
     if( !(rc=overwrite_filep( pub_fname )) ) {
        if( !(pub_io = iobuf_create( pub_fname )) )
@@ -226,7 +338,14 @@ generate_keypair()
     write_comment( pub_io, "#public key created by G10 pre-release " VERSION );
     write_comment( sec_io, "#secret key created by G10 pre-release " VERSION );
 
-    gen_rsa(nbits, pub_io, sec_io);
+    if( algo == PUBKEY_ALGO_ELGAMAL )
+       gen_elg(nbits, pub_io, sec_io);
+  #ifdef HAVE_RSA_CIPHER
+    else if( algo == PUBKEY_ALGO_RSA )
+       gen_rsa(nbits, pub_io, sec_io);
+  #endif
+    else
+       log_bug(NULL);
     write_uid(pub_io, uid );
     write_uid(sec_io, uid );
     m_free(uid);
diff --git a/g10/keyid.c b/g10/keyid.c
new file mode 100644 (file)
index 0000000..0e2dad9
--- /dev/null
@@ -0,0 +1,88 @@
+/* keyid.c - jeyid and fingerprint handling
+ *     Copyright (c) 1997 by Werner Koch (dd9jn)
+ *
+ * This file is part of G10.
+ *
+ * G10 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.
+ *
+ * G10 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 <assert.h>
+#include "util.h"
+#include "main.h"
+#include "packet.h"
+#include "options.h"
+#include "mpi.h"
+#include "keydb.h"
+
+
+
+
+/****************
+ * Get the keyid from the secret key certificate and put it into keyid
+ * if this is not NULL. Return the 32 low bits of the keyid.
+ */
+u32
+keyid_from_skc( PKT_seckey_cert *skc, u32 *keyid )
+{
+    u32 lowbits;
+    u32 dummy_keyid[2];
+
+    if( !keyid )
+       keyid = dummy_keyid;
+
+    if( skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
+       lowbits = mpi_get_keyid( skc->d.elg.y, keyid );
+    }
+    else if( skc->pubkey_algo == PUBKEY_ALGO_RSA ) {
+       lowbits = mpi_get_keyid( skc->d.rsa.rsa_n, keyid );
+    }
+    else
+       log_bug(NULL);
+
+    return lowbits;
+}
+
+
+/****************
+ * Get the keyid from the public key certificate and put it into keyid
+ * if this is not NULL. Return the 32 low bits of the keyid.
+ */
+u32
+keyid_from_pkc( PKT_pubkey_cert *pkc, u32 *keyid )
+{
+    u32 lowbits;
+    u32 dummy_keyid[2];
+
+    if( !keyid )
+       keyid = dummy_keyid;
+
+    if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
+       lowbits = mpi_get_keyid( pkc->d.elg.y, keyid );
+    }
+    else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
+       lowbits = mpi_get_keyid( pkc->d.rsa.rsa_n, keyid );
+    }
+    else
+       log_bug(NULL);
+
+    return lowbits;
+}
+
+
index 9d0f07a..7085634 100644 (file)
 #define G10_MAIN_H
 #include "types.h"
 #include "iobuf.h"
+#include "cipher.h"
+
+#define DEFAULT_CIPHER_ALGO  CIPHER_ALGO_BLOWFISH
+#define DEFAULT_PUBKEY_ALGO  PUBKEY_ALGO_ELGAMAL
+#define DEFAULT_DIGEST_ALGO  DIGEST_ALGO_RMD160
 
 /*-- encode.c --*/
 int encode_symmetric( const char *filename );
@@ -37,4 +42,11 @@ void generate_keypair(void);
 int overwrite_filep( const char *fname );
 IOBUF open_outfile( const char *fname );
 
+/*-- seskey.c --*/
+void make_session_key( DEK *dek );
+MPI encode_session_key( DEK *dek, unsigned nbits );
+MPI encode_rmd160_value( byte *md, unsigned len, unsigned nbits );
+MPI encode_md5_value( byte *md, unsigned len, unsigned nbits );
+
+
 #endif /*G10_MAIN_H*/
index 45cb8fb..6c7e32f 100644 (file)
@@ -30,6 +30,7 @@
 #include "cipher.h"
 #include "keydb.h"
 #include "filter.h"
+#include "main.h"
 
 static int opt_list=1; /* and list the data packets to stdout */
 
@@ -122,8 +123,9 @@ proc_packets( IOBUF a )
                     puts("      (orphaned)");
            }
            if( pkt->pkc_parent ) {
-               if( pkt->pkc_parent->pubkey_algo == PUBKEY_ALGO_RSA ) {
-                   mpi_get_keyid( pkt->pkc_parent->d.rsa.rsa_n, keyid );
+               if( pkt->pkc_parent->pubkey_algo == PUBKEY_ALGO_ELGAMAL
+                   || pkt->pkc_parent->pubkey_algo == PUBKEY_ALGO_RSA ) {
+                   keyid_from_pkc( pkt->pkc_parent, keyid );
                    cache_user_id( pkt->pkt.user_id, keyid );
                }
            }
@@ -158,6 +160,30 @@ proc_packets( IOBUF a )
                result = -1;
                printstr(lvl0, "sig: from %s\n", ustr );
            }
+           else if(sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
+               md_handle.algo = sig->d.elg.digest_algo;
+               if( sig->d.elg.digest_algo == DIGEST_ALGO_RMD160 ) {
+                   if( sig->sig_class == 0x00 )
+                       md_handle.u.rmd = rmd160_copy( mfx.rmd160 );
+                   else {
+                       md_handle.u.rmd = rmd160_copy(pkt->pkc_parent->mfx.rmd160);
+                       rmd160_write(md_handle.u.rmd, pkt->user_parent->name,
+                                                     pkt->user_parent->len);
+                   }
+                   result = signature_check( sig, md_handle );
+                   rmd160_close(md_handle.u.rmd);
+               }
+               else if( sig->d.elg.digest_algo == DIGEST_ALGO_MD5
+                        && sig->sig_class != 0x00 ) {
+                   md_handle.u.md5 = md5_copy(pkt->pkc_parent->mfx.md5);
+                   md5_write(md_handle.u.md5, pkt->user_parent->name,
+                                              pkt->user_parent->len);
+                   result = signature_check( sig, md_handle );
+                   md5_close(md_handle.u.md5);
+               }
+               else
+                   result = G10ERR_DIGEST_ALGO;
+           }
            else if(sig->pubkey_algo == PUBKEY_ALGO_RSA ) {
                md_handle.algo = sig->d.rsa.digest_algo;
                if( sig->d.rsa.digest_algo == DIGEST_ALGO_RMD160 ) {
@@ -204,7 +230,8 @@ proc_packets( IOBUF a )
            enc = pkt->pkt.pubkey_enc;
            printf("enc: encrypted by a pubkey with keyid %08lX\n",
                                                        enc->keyid[1] );
-           if( enc->pubkey_algo == PUBKEY_ALGO_RSA ) {
+           if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL
+               || enc->pubkey_algo == PUBKEY_ALGO_RSA  ) {
                m_free(dek ); /* paranoid: delete a pending DEK */
                dek = m_alloc_secure( sizeof *dek );
                if( (result = get_session_key( enc, dek )) ) {
index f57dce1..480fb54 100644 (file)
 #include "filter.h"
 
 
-#define PKT_PUBKEY_ENC  1  /* public key encrypted packet */
-#define PKT_SIGNATURE   2  /* secret key encrypted packet */
-#define PKT_SECKEY_CERT  5  /* secret key certificate */
-#define PKT_PUBKEY_CERT  6  /* public key certificate */
-#define PKT_COMPR_DATA  8  /* compressed data packet */
-#define PKT_ENCR_DATA   9  /* conventional encrypted data */
-#define PKT_PLAINTEXT  11  /* plaintext data with filename and mode */
-#define PKT_RING_TRUST 12  /* keyring trust packet */
-#define PKT_USER_ID    13  /* user id packet */
-#define PKT_COMMENT    14  /* comment packet */
+#define PKT_PUBKEY_ENC     1  /* public key encrypted packet */
+#define PKT_SIGNATURE      2  /* secret key encrypted packet */
+#define PKT_SESSION_KEY     3  /* session key packet (OpenPGP)*/
+#define PKT_ONEPASS_SIG     4  /* one pass sig packet (OpenPGP)*/
+#define PKT_SECKEY_CERT     5  /* secret key certificate */
+#define PKT_PUBKEY_CERT     6  /* public key certificate */
+#define PKT_SECKEY_SUBCERT  7  /* secret subkey certificate (OpenPGP) */
+#define PKT_COMPR_DATA     8  /* compressed data packet */
+#define PKT_ENCR_DATA      9  /* conventional encrypted data */
+#define PKT_MARKER        10  /* marker packet (OpenPGP) */
+#define PKT_PLAINTEXT     11  /* plaintext data with filename and mode */
+#define PKT_RING_TRUST    12  /* keyring trust packet */
+#define PKT_USER_ID       13  /* user id packet */
+#define PKT_COMMENT       14  /* comment packet */
+#define PKT_PUBKEY_SUBCERT 14  /* subkey certificate (OpenPGP) */
+#define PKT_NEW_COMMENT    16  /* new comment packet (OpenPGP) */
 
 typedef struct packet_struct PACKET;
 
@@ -48,6 +54,9 @@ typedef struct {
       struct {
        MPI  rsa_integer;   /* integer containing the DEK */
       } rsa;
+      struct {
+       MPI  a, b;          /* integers with the enciphered DEK */
+      } elg;
     } d;
 } PKT_pubkey_enc;
 
@@ -60,10 +69,15 @@ typedef struct {
                            /* (PUBKEY_ALGO_xxx) */
     union {
       struct {
-       byte digest_algo;   /* algorithm used for digest (DIGEST_ALGO_xxxx) */
+       byte digest_algo;     /* algorithm used for digest (DIGEST_ALGO_xxxx) */
        byte digest_start[2]; /* first 2 byte of the digest */
-       MPI  rsa_integer;   /* the encrypted digest */
+       MPI  rsa_integer;     /* the encrypted digest */
       } rsa;
+      struct {
+       byte digest_algo;     /* algorithm used for digest (DIGEST_ALGO_xxxx) */
+       byte digest_start[2]; /* first 2 byte of the digest */
+       MPI  a, b;            /* integers with the digest */
+      } elg;
     } d;
 } PKT_signature;
 
@@ -78,6 +92,11 @@ typedef struct {
        MPI rsa_n;          /* public modulus */
        MPI rsa_e;          /* public exponent */
       } rsa;
+      struct {
+       MPI p;              /* prime */
+       MPI g;              /* group generator */
+       MPI y;              /* g^x mod p */
+      } elg;
     } d;
 } PKT_pubkey_cert;
 
@@ -106,6 +125,24 @@ typedef struct {
          } blowfish;
        } protect;
       } rsa;
+      struct {
+       MPI p;              /* prime */
+       MPI g;              /* group generator */
+       MPI y;              /* g^x mod p */
+       MPI x;              /* secret exponent */
+       u16 csum;           /* checksum */
+       u16 calc_csum;      /* and a place to store the calculated csum */
+       byte is_protected;  /* The above infos are protected and must */
+                           /* be deciphered before use */
+       byte protect_algo;  /* cipher used to protect the secret informations*/
+       union {             /* information for the protection */
+         struct {
+           byte iv[8];     /* initialization vector for CFB mode */
+                           /* when protected, the MPIs above are pointers
+                            * to plain storage */
+         } blowfish;
+       } protect;
+      } elg;
     } d;
 } PKT_seckey_cert;
 
index 35fc6d7..569657c 100644 (file)
@@ -148,6 +148,7 @@ parse_packet( IOBUF inp, PACKET *pkt )
        rc = parse_certificate(inp, pkttype, pktlen, hdr, hdrlen, pkt );
        break;
       case PKT_SECKEY_CERT:
+      case PKT_SECKEY_SUBCERT:
        pkt->pkt.seckey_cert = m_alloc_clear(sizeof *pkt->pkt.seckey_cert );
        rc = parse_certificate(inp, pkttype, pktlen, hdr, hdrlen, pkt );
        break;
@@ -230,7 +231,19 @@ parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
     if( list_mode )
        printf(":public key packet: keyid %08lX%08lX\n",
                                        k->keyid[0], k->keyid[1]);
-    if( k->pubkey_algo == PUBKEY_ALGO_RSA ) {
+    if( k->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
+       n = pktlen;
+       k->d.elg.a = mpi_decode(inp, &n ); pktlen -=n;
+       k->d.elg.b = mpi_decode(inp, &n ); pktlen -=n;
+       if( list_mode ) {
+           printf("\telg a: ");
+           mpi_print(stdout, k->d.elg.a, mpi_print_mode );
+           printf("\n\telg b: ");
+           mpi_print(stdout, k->d.elg.b, mpi_print_mode );
+           putchar('\n');
+       }
+    }
+    else if( k->pubkey_algo == PUBKEY_ALGO_RSA ) {
        n = pktlen;
        k->d.rsa.rsa_integer = mpi_decode(inp, &n ); pktlen -=n;
        if( list_mode ) {
@@ -276,7 +289,29 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
               "\tversion %d, created %lu, md5len %d, sigclass %02x\n",
                sig->keyid[0], sig->keyid[1],
                version, sig->timestamp, md5_len, sig->sig_class );
-    if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) {
+    if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
+       if( pktlen < 5 ) {
+           log_error("packet(%d) too short\n", pkttype);
+           goto leave;
+       }
+       sig->d.elg.digest_algo = iobuf_get_noeof(inp); pktlen--;
+       sig->d.elg.digest_start[0] = iobuf_get_noeof(inp); pktlen--;
+       sig->d.elg.digest_start[1] = iobuf_get_noeof(inp); pktlen--;
+       n = pktlen;
+       sig->d.elg.a = mpi_decode(inp, &n ); pktlen -=n;
+       sig->d.elg.b = mpi_decode(inp, &n ); pktlen -=n;
+       if( list_mode ) {
+           printf("\tdigest algo %d, begin of digest %02x %02x\n",
+                   sig->d.elg.digest_algo,
+                   sig->d.elg.digest_start[0], sig->d.elg.digest_start[1] );
+           printf("\telg a: ");
+           mpi_print(stdout, sig->d.elg.a, mpi_print_mode );
+           printf("\n\telg b: ");
+           mpi_print(stdout, sig->d.elg.a, mpi_print_mode );
+           putchar('\n');
+       }
+    }
+    else if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) {
        if( pktlen < 5 ) {
            log_error("packet(%d) too short\n", pkttype);
            goto leave;
@@ -315,7 +350,7 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
     unsigned n;
     unsigned long timestamp;
     unsigned short valid_period;
-    MPI rsa_pub_mod, rsa_pub_exp;
+    int is_v4=0;
 
     if( pkttype == PKT_PUBKEY_CERT ) {
        pkt->pkt.pubkey_cert->mfx.md5 = md5_open(0);
@@ -331,13 +366,18 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
        goto leave;
     }
     version = iobuf_get_noeof(inp); pktlen--;
-    if( version != 2 && version != 3 ) {
+    if( version == 4 )
+       is_v4=1;
+    else if( version != 2 && version != 3 ) {
        log_error("packet(%d) with unknown version %d\n", pkttype, version);
        goto leave;
     }
 
     timestamp = read_32(inp); pktlen -= 4;
-    valid_period = read_16(inp); pktlen -= 2;
+    if( is_v4 )
+       valid_period = 0;
+    else
+       valid_period = read_16(inp); pktlen -= 2;
     algorithm = iobuf_get_noeof(inp); pktlen--;
     if( list_mode )
        printf(":%s key certification packet:\n"
@@ -355,7 +395,76 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
        pkt->pkt.pubkey_cert->pubkey_algo = algorithm;
     }
 
-    if( algorithm == PUBKEY_ALGO_RSA ) {
+    if( algorithm == PUBKEY_ALGO_ELGAMAL ) {
+       MPI elg_p, elg_g, elg_y;
+       n = pktlen; elg_p = mpi_decode(inp, &n ); pktlen -=n;
+       n = pktlen; elg_g = mpi_decode(inp, &n ); pktlen -=n;
+       n = pktlen; elg_y = mpi_decode(inp, &n ); pktlen -=n;
+       if( list_mode ) {
+           printf(  "\telg p:  ");
+           mpi_print(stdout, elg_p, mpi_print_mode  );
+           printf("\n\telg g: ");
+           mpi_print(stdout, elg_g, mpi_print_mode  );
+           printf("\n\telg y: ");
+           mpi_print(stdout, elg_y, mpi_print_mode  );
+           putchar('\n');
+       }
+       if( pkttype == PKT_PUBKEY_CERT ) {
+           pkt->pkt.pubkey_cert->d.elg.p = elg_p;
+           pkt->pkt.pubkey_cert->d.elg.g = elg_g;
+           pkt->pkt.pubkey_cert->d.elg.y = elg_y;
+       }
+       else {
+           PKT_seckey_cert *cert = pkt->pkt.seckey_cert;
+           byte temp[8];
+           byte *mpibuf;
+
+           pkt->pkt.seckey_cert->d.elg.p = elg_p;
+           pkt->pkt.seckey_cert->d.elg.g = elg_g;
+           pkt->pkt.seckey_cert->d.elg.y = elg_y;
+           cert->d.elg.protect_algo = iobuf_get_noeof(inp); pktlen--;
+           if( list_mode )
+               printf(  "\tprotect algo: %d\n", cert->d.elg.protect_algo);
+           if( cert->d.elg.protect_algo ) {
+               cert->d.elg.is_protected = 1;
+               for(i=0; i < 8 && pktlen; i++, pktlen-- )
+                   temp[i] = iobuf_get_noeof(inp);
+               if( list_mode ) {
+                   printf(  "\tprotect IV: ");
+                   for(i=0; i < 8; i++ )
+                       printf(" %02x", temp[i] );
+                   putchar('\n');
+               }
+               if( cert->d.elg.protect_algo == CIPHER_ALGO_BLOWFISH )
+                   memcpy(cert->d.elg.protect.blowfish.iv, temp, 8 );
+           }
+           else
+               cert->d.elg.is_protected = 0;
+
+           n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
+           cert->d.elg.x = (MPI)mpibuf;
+
+           cert->d.elg.csum = read_16(inp); pktlen -= 2;
+           cert->d.elg.calc_csum = 0;
+           if( list_mode ) {
+               printf("\t[secret value x is not shown]\n"
+                      "\tchecksum: %04hx\n", cert->d.elg.csum);
+           }
+           if( !cert->d.elg.is_protected ) { /* convert buffer to MPIs */
+               mpibuf = (byte*)cert->d.elg.x;
+               cert->d.elg.calc_csum += checksum( mpibuf );
+               cert->d.elg.x = mpi_decode_buffer( mpibuf );
+               m_free( mpibuf );
+               log_mpidump("elg p=", cert->d.elg.p );
+               log_mpidump("elg g=", cert->d.elg.g );
+               log_mpidump("elg y=", cert->d.elg.y );
+               log_mpidump("elg x=", cert->d.elg.x );
+           }
+       }
+    }
+    else if( algorithm == PUBKEY_ALGO_RSA ) {
+       MPI rsa_pub_mod, rsa_pub_exp;
+
        n = pktlen; rsa_pub_mod = mpi_decode(inp, &n ); pktlen -=n;
        n = pktlen; rsa_pub_exp = mpi_decode(inp, &n ); pktlen -=n;
        if( list_mode ) {
index 93bdff9..58da1ae 100644 (file)
@@ -39,24 +39,50 @@ int
 get_session_key( PKT_pubkey_enc *k, DEK *dek )
 {
     int i, j, c, rc = 0;
-    RSA_secret_key  *skey = m_alloc_secure( sizeof *skey );
     MPI dek_frame = mpi_alloc_secure(40);
     u16 csum, csum2;
+    PKT_seckey_cert *skc = m_alloc_clear( sizeof *skc );
 
-    if( k->pubkey_algo != PUBKEY_ALGO_RSA ) {
-       rc = G10ERR_PUBKEY_ALGO; /* unsupported algorithm */
+    skc->pubkey_algo = k->pubkey_algo;  /* we want a pubkey with this algo*/
+    if( (rc = get_seckey( skc, k->keyid )) )
        goto leave;
+
+    if( k->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
+       ELG_secret_key skey;
+
+       if( DBG_CIPHER ) {
+           log_mpidump("Encr DEK a:", k->d.elg.a );
+           log_mpidump("     DEK b:", k->d.elg.b );
+       }
+       skey.p = skc->d.elg.p;
+       skey.g = skc->d.elg.g;
+       skey.y = skc->d.elg.y;
+       skey.x = skc->d.elg.x;
+       elg_decipher( dek_frame, k->d.elg.a, k->d.elg.b, &skey );
+       memset( &skey, 0, sizeof skey );
     }
+    else if( k->pubkey_algo == PUBKEY_ALGO_RSA ) {
+       RSA_secret_key skey;
 
-    /* get the secret key for the given public key
-     * and decode the rsa_integer
-     */
-    if( (rc = get_seckey( skey, k->keyid )) )
+       if( DBG_CIPHER )
+           log_mpidump("Encr DEK frame:", k->d.rsa.rsa_integer );
+
+       skey.e = skc->d.rsa.rsa_e;
+       skey.n = skc->d.rsa.rsa_n;
+       skey.p = skc->d.rsa.rsa_p;
+       skey.q = skc->d.rsa.rsa_q;
+       skey.d = skc->d.rsa.rsa_d;
+       skey.u = skc->d.rsa.rsa_u;
+       rsa_secret( dek_frame, k->d.rsa.rsa_integer, &skey );
+       memset( &skey, 0, sizeof skey );
+    }
+    else {
+       rc = G10ERR_PUBKEY_ALGO; /* unsupported algorithm */
        goto leave;
+    }
+    free_seckey_cert( skc ); skc = NULL;
+
 
-    if( DBG_CIPHER )
-       log_mpidump("Encr DEK frame:", k->d.rsa.rsa_integer );
-    rsa_secret( dek_frame, k->d.rsa.rsa_integer, skey );
     /* Now get the DEK (data encryption key) from the dek_frame
      *
      * Old versions encode the DEK in in this format (msb is left):
@@ -87,7 +113,7 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
     }
     if( c != 2 )  /* somethink is wrong */
        { rc = G10ERR_WRONG_SECKEY; goto leave; }
-    /* look for the zeor byte */
+    /* look for the zero byte */
     for(i--; i > 4 ; i-- )
        if( !mpi_getbyte(dek_frame,i) )
            break;
@@ -95,10 +121,10 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
        { rc = G10ERR_WRONG_SECKEY; goto leave; }
     /* next byte indicates the used cipher */
     switch( mpi_getbyte(dek_frame, --i ) ) {
-      case 1:
+      case CIPHER_ALGO_IDEA:
        rc = G10ERR_NI_CIPHER;
        goto leave;
-      case 42:
+      case CIPHER_ALGO_BLOWFISH:
        if( i != 22 ) /* length of blowfish is 20 (+2 bytes checksum) */
            { rc = G10ERR_WRONG_SECKEY; goto leave; }
        dek->algo = CIPHER_ALGO_BLOWFISH;
@@ -122,7 +148,8 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
 
   leave:
     mpi_free(dek_frame);
-    m_free(skey);
+    if( skc )
+       free_seckey_cert( skc );
     return rc;
 }
 
index c103de5..4e1a384 100644 (file)
@@ -30,6 +30,9 @@
 #include "keydb.h"
 #include "cipher.h"
 
+#if  BLOWFISH_BLOCKSIZE != 8
+  #error unsupportted blocksize
+#endif
 
 static u16
 checksum( byte *p )
@@ -44,11 +47,9 @@ checksum( byte *p )
 }
 
 
-/****************
- * Check the secret key certificate
- */
-int
-check_secret_key( PKT_seckey_cert *cert )
+
+static int
+check_elg( PKT_seckey_cert *cert )
 {
     byte iv[8];
     byte *mpibuf;
@@ -56,13 +57,73 @@ check_secret_key( PKT_seckey_cert *cert )
     MPI temp_mpi;
     int res;
     u32 keyid[2];
+    ELG_secret_key skey;
 
-#if  BLOWFISH_BLOCKSIZE != 8
-  #error unsupportted blocksize
-#endif
+    if( cert->d.elg.is_protected ) { /* remove the protection */
+       DEK *dek = NULL;
+       BLOWFISH_context *blowfish_ctx=NULL;
+
+       switch( cert->d.elg.protect_algo ) {
+         case CIPHER_ALGO_NONE: log_bug(NULL); break;
+         case CIPHER_ALGO_BLOWFISH:
+           keyid_from_skc( cert, keyid );
+           dek = get_passphrase_hash( keyid, NULL );
+           m_free(dek); /* pw is in secure memory, so m_free() burns it */
+           memset( iv, 0, BLOWFISH_BLOCKSIZE );
+           blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
+           blowfish_setiv( blowfish_ctx, iv );
+           blowfish_decode_cfb( blowfish_ctx,
+                                cert->d.elg.protect.blowfish.iv,
+                                cert->d.elg.protect.blowfish.iv, 8 );
+           cert->d.elg.calc_csum = 0;
+           mpibuf = (byte*)cert->d.elg.x;
+           n = ((mpibuf[0] << 8) | mpibuf[1])-2;
+           blowfish_decode_cfb( blowfish_ctx, mpibuf+4, mpibuf+4, n );
+           cert->d.elg.calc_csum += checksum( mpibuf );
+           cert->d.elg.x = mpi_decode_buffer( mpibuf );
+           m_free( mpibuf );
+           m_free( blowfish_ctx );
+           cert->d.elg.is_protected = 0;
+           /* now let's see wether we have used the right passphrase */
+           if( cert->d.elg.calc_csum != cert->d.elg.csum )
+               return G10ERR_BAD_PASS;
 
-    if( cert->pubkey_algo != PUBKEY_ALGO_RSA )
-       return G10ERR_PUBKEY_ALGO; /* unsupport algorithm */
+           skey.p = cert->d.elg.p;
+           skey.g = cert->d.elg.g;
+           skey.y = cert->d.elg.y;
+           skey.x = cert->d.elg.x;
+           res = elg_check_secret_key( &skey );
+           memset( &skey, 0, sizeof skey );
+           if( !res )
+               return G10ERR_BAD_PASS;
+           break;
+
+         default:
+           return G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
+       }
+    }
+    /* must check the checksum here, because we didn't do it when
+     * parsing an unprotected certificate */
+    if( cert->d.elg.calc_csum != cert->d.elg.csum ) {
+       log_error("checksum in secret key certificate is wrong\n");
+       log_debug("stored csum=%04hx calculated csum=%04hx\n",
+                  cert->d.elg.csum, cert->d.elg.calc_csum );
+       return G10ERR_CHECKSUM;
+    }
+    return 0;
+}
+
+
+#ifdef HAVE_RSA_CIPHER
+static int
+check_rsa( PKT_seckey_cert *cert )
+{
+    byte iv[8];
+    byte *mpibuf;
+    u16 n;
+    MPI temp_mpi;
+    int res;
+    u32 keyid[2];
 
     if( cert->d.rsa.is_protected ) { /* remove the protection */
        DEK *dek = NULL;
@@ -73,7 +134,7 @@ check_secret_key( PKT_seckey_cert *cert )
            log_bug("unprotect seckey_cert is flagged protected\n");
            break;
          case CIPHER_ALGO_BLOWFISH:
-           mpi_get_keyid( cert->d.rsa.rsa_n , keyid );
+           keyid_from_skc( cert, keyid );
            dek = get_passphrase_hash( keyid, NULL );
 
            m_free(dek); /* pw is in secure memory, so m_free() burns it */
@@ -133,5 +194,24 @@ check_secret_key( PKT_seckey_cert *cert )
     }
     return 0;
 }
+#endif /*HAVE_RSA_CIPHER*/
+
+
+
 
+/****************
+ * Check the secret key certificate
+ */
+int
+check_secret_key( PKT_seckey_cert *cert )
+{
+    if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
+       return check_elg( cert );
+  #ifdef HAVE_RSA_CIPHER
+    else if( cert->pubkey_algo == PUBKEY_ALGO_RSA )
+       return check_rsa( cert );
+  #endif
+    else
+       return G10ERR_PUBKEY_ALGO;
+}
 
index 317623e..5e94476 100644 (file)
@@ -26,6 +26,7 @@
 #include "util.h"
 #include "cipher.h"
 #include "mpi.h"
+#include "main.h"
 
 
 
@@ -73,7 +74,7 @@ encode_session_key( DEK *dek, unsigned nbits )
      *    0  2  RND(n bytes)  0  A  DEK(k bytes)  CSUM(2 bytes)
      *
      * RND are non-zero random bytes.
-     * A   is the cipher algorithm ( 42 for Blowfish )
+     * A   is the cipher algorithm
      * DEK is the encryption key (session key) length k depends on the
      *    cipher algorithm (20 is used with blowfish).
      * CSUM is the 16 bit checksum over the DEK
@@ -106,7 +107,7 @@ encode_session_key( DEK *dek, unsigned nbits )
 MPI
 encode_rmd160_value( byte *md, unsigned len, unsigned nbits )
 {
-    static byte asn[18] = /* stored reverse FIXME: need other values*/
+    static byte asn[18] = /* FIXME: need other values*/
          { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48,
            0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 };
     int nframe = (nbits+7) / 8;
@@ -119,7 +120,7 @@ encode_rmd160_value( byte *md, unsigned len, unsigned nbits )
 
     /* We encode the MD in this way:
      *
-     *    0  42 PAD(n bytes)   0  ASN(18 bytes)  MD(20 bytes)
+     *    0  A PAD(n bytes)   0  ASN(18 bytes)  MD(20 bytes)
      *
      * PAD consists of FF bytes.
      */
@@ -138,3 +139,43 @@ encode_rmd160_value( byte *md, unsigned len, unsigned nbits )
     return frame;
 }
 
+
+/****************
+ * Encode a md5 message digest of LEN bytes into NBITS.
+ * returns: A mpi with the session key (caller must free)
+ */
+MPI
+encode_md5_value( byte *md, unsigned len, unsigned nbits )
+{
+    static byte asn[18] =
+         { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48,
+           0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 };
+    int nframe = (nbits+7) / 8;
+    byte *p;
+    MPI frame;
+    int i,n,c;
+
+    if( (nbits % BITS_PER_MPI_LIMB) || nframe < 38 || len != 16 )
+       log_bug("can't encode a %d bit MD into a %d bits frame\n",len*8, nbits);
+
+    /* We encode the MD in this way:
+     *
+     *    0  A PAD(n bytes)   0  ASN(18 bytes)  MD(16 bytes)
+     *
+     * PAD consists of FF bytes.
+     */
+    frame = mpi_alloc_secure( nframe / BYTES_PER_MPI_LIMB );
+    n = 0;
+    for(i=16-1; i >= 0; i--, n++ )
+       mpi_putbyte(frame, n, md[i] );
+    for( i=18-1; i >= 0; i--, n++ )
+       mpi_putbyte(frame, n, asn[i] );
+    mpi_putbyte(frame, n++, 0 );
+    while( n < nframe-2 )
+       mpi_putbyte(frame, n++, 0xff );
+    mpi_putbyte(frame, n++, DIGEST_ALGO_MD5 );
+    mpi_putbyte(frame, n++, 0 );
+    assert( n == nframe );
+    return frame;
+}
+
index 75e8006..ff21258 100644 (file)
@@ -29,6 +29,7 @@
 #include "mpi.h"
 #include "keydb.h"
 #include "cipher.h"
+#include "main.h"
 
 
 /****************
@@ -40,7 +41,7 @@ int
 signature_check( PKT_signature *sig, MD_HANDLE digest )
 {
     PKT_pubkey_cert *pkc = m_alloc_clear( sizeof *pkc );
-    MPI result = mpi_alloc(35);
+    MPI result = NULL;
     int rc=0, i, j, c, old_enc;
     byte *dp;
 
@@ -50,162 +51,181 @@ signature_check( PKT_signature *sig, MD_HANDLE digest )
        goto leave;
     }
 
-    if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
-       RSA_public_key pkey;
-       pkey.n = pkc->d.rsa.rsa_n;
-       pkey.e = pkc->d.rsa.rsa_e;
-       rsa_public( result, sig->d.rsa.rsa_integer, &pkey );
-    }
-    else {
-       log_debug("signature_check: unsupported pubkey algo %d\n",
-                       pkc->pubkey_algo );
-       rc = G10ERR_PUBKEY_ALGO;
-       goto leave;
-    }
-
+    if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
+       ELG_public_key pkey;
 
-    /* Now RESULT contains the deciphered session key.
-     *
-     * The session key is stored in different ways:
-     *
-     * Old versions encodes the digest in in this format (msb is left):
-     *
-     *    0  1  MD5(16 bytes)  0  PAD(n bytes)  1
-     *
-     * Later versions encodes the digest like this:
-     *
-     *    0  1  PAD(n bytes)   0  ASN(18 bytes)  MD(16 bytes)
-     *
-     * RIPE MD 160 digests are encoded like this:
-     *
-     *    0  42 PAD(n bytes)   0  ASN(18 bytes)  MD(20 bytes)
-     *
-     * FIXME: we should use another ASN!
-     *
-     * PAD consists of FF bytes.
-     * ASN is here the constant: 3020300c06082a864886f70d020505000410
-     */
-    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;
+       if( sig->d.elg.digest_algo == DIGEST_ALGO_RMD160 ) {
+           /* complete the digest */
+           rmd160_putchar( digest.u.rmd, sig->sig_class );
+           {   u32 a = sig->timestamp;
+               rmd160_putchar( digest.u.rmd, (a >> 24) & 0xff );
+               rmd160_putchar( digest.u.rmd, (a >> 16) & 0xff );
+               rmd160_putchar( digest.u.rmd, (a >>  8) & 0xff );
+               rmd160_putchar( digest.u.rmd,  a        & 0xff );
+           }
+           dp = rmd160_final( digest.u.rmd );
+           result = encode_rmd160_value( dp, 20, mpi_get_nbits(pkc->d.elg.p));
        }
-       else if( ++j == 18 && c != 1 )
-           break;
-       else if( j == 19 && c == 0 ) {
-           old_enc++;
-           break;
+       else if( sig->d.rsa.digest_algo == DIGEST_ALGO_MD5 ) {
+           md5_putchar( digest.u.md5, sig->sig_class );
+           {   u32 a = sig->timestamp;
+               md5_putchar( digest.u.md5, (a >> 24) & 0xff );
+               md5_putchar( digest.u.md5, (a >> 16) & 0xff );
+               md5_putchar( digest.u.md5, (a >>  8) & 0xff );
+               md5_putchar( digest.u.md5,  a        & 0xff );
+           }
+           md5_final( digest.u.md5 );
+           dp = md5_read( digest.u.md5 );
+           result = encode_md5_value( dp, 16, mpi_get_nbits(pkc->d.elg.p));
        }
+       else {
+           rc = G10ERR_DIGEST_ALGO;
+           goto leave;
+       }
+
+       pkey.p = pkc->d.elg.p;
+       pkey.g = pkc->d.elg.g;
+       pkey.y = pkc->d.elg.y;
+       if( !elg_verify( sig->d.elg.a, sig->d.elg.b, result, &pkey ) )
+           rc = G10ERR_BAD_SIGN;
     }
-    if( old_enc ) {
-       log_error("old encoding scheme is not supported\n");
-       rc = G10ERR_GENERAL;
-       goto leave;
-    }
+    else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
+       RSA_public_key pkey;
 
-    if( sig->d.rsa.digest_algo == DIGEST_ALGO_RMD160 ) {
-       static byte asn[18] = /* stored reverse FIXME: need other values*/
-             { 0x10, 0x04, 0x00, 0x05, 0x05, 0x02, 0x0d, 0xf7, 0x86,
-               0x48, 0x86, 0x2a, 0x08, 0x06, 0x0c, 0x30, 0x20, 0x30 };
+       result = mpi_alloc(40);
+       pkey.n = pkc->d.rsa.rsa_n;
+       pkey.e = pkc->d.rsa.rsa_e;
+       rsa_public( result, sig->d.rsa.rsa_integer, &pkey );
 
-       for(i=20,j=0; (c=mpi_getbyte(result, i)) != -1 && j < 18; i++, j++ )
-           if( asn[j] != c )
+       old_enc = 0;
+       for(i=j=0; (c=mpi_getbyte(result, i)) != -1; i++ ) {
+           if( !j ) {
+               if( !i && c != 1 )
+                   break;
+               else if( i && c == 0xff )
+                   ; /* skip the padding */
+               else if( i && !c )
+                   j++;
+               else
+                   break;
+           }
+           else if( ++j == 18 && c != 1 )
                break;
-       if( j != 18 || c ) { /* ASN is wrong */
-           rc = G10ERR_BAD_PUBKEY;
-           goto leave;
-       }
-       for(i++; (c=mpi_getbyte(result, i)) != -1; i++ )
-           if( c != 0xff  )
+           else if( j == 19 && c == 0 ) {
+               old_enc++;
                break;
-       i++;
-       if( c != DIGEST_ALGO_RMD160 || mpi_getbyte(result, i) ) {
-           /* Padding or leading bytes in signature is wrong */
-           rc = G10ERR_BAD_PUBKEY;
-           goto leave;
+           }
        }
-       if( mpi_getbyte(result, 19) != sig->d.rsa.digest_start[0]
-           || mpi_getbyte(result, 18) != sig->d.rsa.digest_start[1] ) {
-           /* Wrong key used to check the signature */
-           rc = G10ERR_BAD_PUBKEY;
+       if( old_enc ) {
+           log_error("old encoding scheme is not supported\n");
+           rc = G10ERR_GENERAL;
            goto leave;
        }
 
-       /* complete the digest */
-       rmd160_putchar( digest.u.rmd, sig->sig_class );
-       {   u32 a = sig->timestamp;
-           rmd160_putchar( digest.u.rmd, (a >> 24) & 0xff );
-           rmd160_putchar( digest.u.rmd, (a >> 16) & 0xff );
-           rmd160_putchar( digest.u.rmd, (a >>  8) & 0xff );
-           rmd160_putchar( digest.u.rmd,  a        & 0xff );
-       }
-       dp = rmd160_final( digest.u.rmd );
-       for(i=19; i >= 0; i--, dp++ )
-           if( mpi_getbyte( result, i ) != *dp ) {
-               rc = G10ERR_BAD_SIGN;
+       if( sig->d.rsa.digest_algo == DIGEST_ALGO_RMD160 ) {
+           static byte asn[18] = /* stored reverse FIXME: need other values*/
+                 { 0x10, 0x04, 0x00, 0x05, 0x05, 0x02, 0x0d, 0xf7, 0x86,
+                   0x48, 0x86, 0x2a, 0x08, 0x06, 0x0c, 0x30, 0x20, 0x30 };
+
+           for(i=20,j=0; (c=mpi_getbyte(result, i)) != -1 && j < 18; i++, j++ )
+               if( asn[j] != c )
+                   break;
+           if( j != 18 || c ) { /* 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 != DIGEST_ALGO_RMD160 || mpi_getbyte(result, i) ) {
+               /* Padding or leading bytes in signature is wrong */
+               rc = G10ERR_BAD_PUBKEY;
+               goto leave;
+           }
+           if( mpi_getbyte(result, 19) != sig->d.rsa.digest_start[0]
+               || mpi_getbyte(result, 18) != sig->d.rsa.digest_start[1] ) {
+               /* Wrong key used to check the signature */
+               rc = G10ERR_BAD_PUBKEY;
                goto leave;
            }
-    }
-    else if( sig->d.rsa.digest_algo == DIGEST_ALGO_MD5 ) {
-       static byte asn[18] = /* stored reverse */
-             { 0x10, 0x04, 0x00, 0x05, 0x05, 0x02, 0x0d, 0xf7, 0x86,
-               0x48, 0x86, 0x2a, 0x08, 0x06, 0x0c, 0x30, 0x20, 0x30 };
 
-       for(i=16,j=0; j < 18 && (c=mpi_getbyte(result, i)) != -1; i++, j++ )
-           if( asn[j] != c )
-               break;
-       if( j != 18 || c ) { /* 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 != DIGEST_ALGO_MD5 || mpi_getbyte(result, i) ) {
-           /* Padding or leading bytes in signature is wrong */
-           rc = G10ERR_BAD_PUBKEY;
-           goto leave;
-       }
-       if( mpi_getbyte(result, 15) != sig->d.rsa.digest_start[0]
-           || mpi_getbyte(result, 14) != sig->d.rsa.digest_start[1] ) {
-           /* Wrong key used to check the signature */
-           rc = G10ERR_BAD_PUBKEY;
-           goto leave;
+           /* complete the digest */
+           rmd160_putchar( digest.u.rmd, sig->sig_class );
+           {   u32 a = sig->timestamp;
+               rmd160_putchar( digest.u.rmd, (a >> 24) & 0xff );
+               rmd160_putchar( digest.u.rmd, (a >> 16) & 0xff );
+               rmd160_putchar( digest.u.rmd, (a >>  8) & 0xff );
+               rmd160_putchar( digest.u.rmd,  a        & 0xff );
+           }
+           dp = rmd160_final( digest.u.rmd );
+           for(i=19; i >= 0; i--, dp++ )
+               if( mpi_getbyte( result, i ) != *dp ) {
+                   rc = G10ERR_BAD_SIGN;
+                   goto leave;
+               }
        }
+       else if( sig->d.rsa.digest_algo == DIGEST_ALGO_MD5 ) {
+           static byte asn[18] = /* stored reverse */
+                 { 0x10, 0x04, 0x00, 0x05, 0x05, 0x02, 0x0d, 0xf7, 0x86,
+                   0x48, 0x86, 0x2a, 0x08, 0x06, 0x0c, 0x30, 0x20, 0x30 };
 
-       /* complete the digest */
-       md5_putchar( digest.u.md5, sig->sig_class );
-       {   u32 a = sig->timestamp;
-           md5_putchar( digest.u.md5, (a >> 24) & 0xff );
-           md5_putchar( digest.u.md5, (a >> 16) & 0xff );
-           md5_putchar( digest.u.md5, (a >>  8) & 0xff );
-           md5_putchar( digest.u.md5,  a        & 0xff );
-       }
-       md5_final( digest.u.md5 );
-       dp = md5_read( digest.u.md5 );
-       for(i=15; i >= 0; i--, dp++ )
-           if( mpi_getbyte( result, i ) != *dp ) {
-               rc = G10ERR_BAD_SIGN;
+           for(i=16,j=0; j < 18 && (c=mpi_getbyte(result, i)) != -1; i++, j++ )
+               if( asn[j] != c )
+                   break;
+           if( j != 18 || c ) { /* 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 != DIGEST_ALGO_MD5 || mpi_getbyte(result, i) ) {
+               /* Padding or leading bytes in signature is wrong */
+               rc = G10ERR_BAD_PUBKEY;
+               goto leave;
+           }
+           if( mpi_getbyte(result, 15) != sig->d.rsa.digest_start[0]
+               || mpi_getbyte(result, 14) != sig->d.rsa.digest_start[1] ) {
+               /* Wrong key used to check the signature */
+               rc = G10ERR_BAD_PUBKEY;
+               goto leave;
+           }
+
+           /* complete the digest */
+           md5_putchar( digest.u.md5, sig->sig_class );
+           {   u32 a = sig->timestamp;
+               md5_putchar( digest.u.md5, (a >> 24) & 0xff );
+               md5_putchar( digest.u.md5, (a >> 16) & 0xff );
+               md5_putchar( digest.u.md5, (a >>  8) & 0xff );
+               md5_putchar( digest.u.md5,  a        & 0xff );
+           }
+           md5_final( digest.u.md5 );
+           dp = md5_read( digest.u.md5 );
+           for(i=15; i >= 0; i--, dp++ )
+               if( mpi_getbyte( result, i ) != *dp ) {
+                   rc = G10ERR_BAD_SIGN;
+                   goto leave;
+               }
+       }
+       else {
+           rc = G10ERR_DIGEST_ALGO;
+           goto leave;
+       }
     }
     else {
-       rc = G10ERR_DIGEST_ALGO;
+       log_debug("signature_check: unsupported pubkey algo %d\n",
+                       pkc->pubkey_algo );
+       rc = G10ERR_PUBKEY_ALGO;
        goto leave;
     }
 
+
   leave:
-    mpi_free( result );
     if( pkc )
        free_pubkey_cert( pkc );
+    mpi_free( result );
     return rc;
 }
 
index e178b5f..e328042 100644 (file)
 #include "../cipher/elgamal.h"
 
 
-#define CIPHER_ALGO_NONE      0
-#define CIPHER_ALGO_IDEA      1     /* used only for documentation */
-#define CIPHER_ALGO_BLOWFISH 42
-#define CIPHER_ALGO_GOST     43
+#define CIPHER_ALGO_NONE        0
+#define CIPHER_ALGO_IDEA        1
+#define CIPHER_ALGO_3DES        2
+#define CIPHER_ALGO_CAST        3
+#define CIPHER_ALGO_BLOWFISH128  4  /* blowfish 128 bit key */
+#define CIPHER_ALGO_ROT_N       5
+#define CIPHER_ALGO_SAFER_SK128  6
+#define CIPHER_ALGO_DES_SK      7
+#define CIPHER_ALGO_BLOWFISH   42  /* blowfish 160 bit key (not in OpenPGP)*/
+#define CIPHER_ALGO_GOST       43  /* (Not in OpenPGP) */
 
 #define PUBKEY_ALGO_RSA       1
-#define PUBKEY_ALGO_ELGAMAL  42
+#define PUBKEY_ALGO_RSA_E     2     /* RSA encrypt only */
+#define PUBKEY_ALGO_RSA_S     3     /* RSA sign only */
+#define PUBKEY_ALGO_ELGAMAL  16
+#define PUBKEY_ALGO_DSA      17
 
 #define DIGEST_ALGO_MD5       1
-#define DIGEST_ALGO_RMD160   42
+#define DIGEST_ALGO_SHA1      2
+#define DIGEST_ALGO_RMD160    3
 
-#define DEFAULT_CIPHER_ALGO  CIPHER_ALGO_BLOWFISH
-#define DEFAULT_PUBKEY_ALGO  PUBKEY_ALGO_RSA
-#define DEFAULT_DIGEST_ALGO  DIGEST_ALGO_RMD160
 
 typedef struct {
     int algo;
@@ -78,12 +85,8 @@ byte get_random_byte( int level );
 extern ushort small_prime_numbers[];
 
 /*-- primegen.c --*/
-MPI generate_random_prime( unsigned nbits );
-
-/*-- seskey.c --*/
-void make_session_key( DEK *dek );
-MPI encode_session_key( DEK *dek, unsigned nbits );
-MPI encode_rmd160_value( byte *md, unsigned len, unsigned nbits );
+MPI generate_secret_prime( unsigned nbits );
+MPI generate_public_prime( unsigned nbits );
 
 
 #endif /*G10_CIPHER_H*/
index 096cffe..25fa696 100644 (file)
@@ -51,6 +51,7 @@ typedef struct mpi_struct {
 #define MPI_NULL NULL
 
 #define mpi_get_nlimbs(a) ((a)->nlimbs)
+#define mpi_is_neg(a)    ((a)->sign)
 
 /*-- mpiutil.c --*/
 
@@ -101,13 +102,16 @@ u32 mpi_get_keyid( MPI a, u32 *keyid );
 /*-- mpi-add.c --*/
 void mpi_add_ui(MPI w, MPI u, ulong v );
 void mpi_add(MPI w, MPI u, MPI v);
+void mpi_addm(MPI w, MPI u, MPI v, MPI m);
 void mpi_sub_ui(MPI w, MPI u, ulong v );
 void mpi_sub( MPI w, MPI u, MPI v);
+void mpi_subm( MPI w, MPI u, MPI v, MPI m);
 
 /*-- mpi-mul.c --*/
 void mpi_mul_ui(MPI w, MPI u, ulong v );
 void mpi_mul_2exp( MPI w, MPI u, ulong cnt);
 void mpi_mul( MPI w, MPI u, MPI v);
+void mpi_mulm( MPI w, MPI u, MPI v, MPI m);
 
 /*-- mpi-div.c --*/
 ulong mpi_fdiv_r_ui( MPI rem, MPI dividend, ulong divisor );
@@ -142,7 +146,7 @@ void mpi_set_bytes( MPI a, unsigned nbits, byte (*fnc)(int), int opaque );
 void mpi_rshift( MPI x, MPI a, unsigned n );
 
 /*-- mpi-inv.c --*/
-void mpi_inv_mod( MPI x, MPI u, MPI v );
+void mpi_invm( MPI x, MPI u, MPI v );
 
 
 #endif /*G10_MPI_H*/
index 2c1aa6c..b9c69af 100644 (file)
@@ -222,3 +222,17 @@ mpi_sub(MPI w, MPI u, MPI v)
 }
 
 
+void
+mpi_addm( MPI w, MPI u, MPI v, MPI m)
+{
+    mpi_add(w, u, v);
+    mpi_fdiv_r( w, w, m );
+}
+
+void
+mpi_subm( MPI w, MPI u, MPI v, MPI m)
+{
+    mpi_sub(w, u, v);
+    mpi_fdiv_r( w, w, m );
+}
+
index f37f4e5..28cde00 100644 (file)
@@ -30,7 +30,7 @@
  *             1 = (a*x) mod n
  */
 void
-mpi_inv_mod( MPI x, MPI a, MPI n )
+mpi_invm( MPI x, MPI a, MPI n )
 {
   #if 0
     MPI u, v, u1, u2, u3, v1, v2, v3, q, t1, t2, t3;
index 03f2b4b..aa5beb7 100644 (file)
@@ -176,3 +176,10 @@ mpi_mul( MPI w, MPI u, MPI v)
 }
 
 
+void
+mpi_mulm( MPI w, MPI u, MPI v, MPI m)
+{
+    mpi_mul(w, u, v);
+    mpi_fdiv_r( w, w, m );
+}
+
index 828b475..28c4985 100644 (file)
@@ -159,7 +159,7 @@ do_inv(void)
        fputs("stack underflow\n", stderr);
        return;
     }
-    mpi_inv_mod( a, stack[stackidx-2], stack[stackidx-1] );
+    mpi_invm( a, stack[stackidx-2], stack[stackidx-1] );
     mpi_set(stack[stackidx-2],a);
     mpi_free(a);
     stackidx--;
index 9c1b86b..8993ba4 100644 (file)
@@ -110,9 +110,13 @@ log_bug( const char *fmt, ... )
     va_list arg_ptr ;
 
     fprintf(stderr, "\nInternal Error%s: ", pidstring  ) ;
-    va_start( arg_ptr, fmt ) ;
-    vfprintf(stderr,fmt,arg_ptr) ;
-    va_end(arg_ptr);
+    if( fmt ) {
+       va_start( arg_ptr, fmt ) ;
+       vfprintf(stderr,fmt,arg_ptr) ;
+       va_end(arg_ptr);
+    }
+    else
+       fputs("Ohhh jeeee ...\n", stderr);
     fflush(stderr);
     abort();
 }