summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>1997-11-24 23:24:04 +0100
committerWerner Koch <wk@gnupg.org>1997-11-24 23:24:04 +0100
commit46900fbd437a134bd16e5030182fb3a219cd370e (patch)
treef13063a7c4896b189c7a3d09791d5464241174c7
parentIDEA removed, signing works (diff)
downloadgnupg2-46900fbd437a134bd16e5030182fb3a219cd370e.tar.xz
gnupg2-46900fbd437a134bd16e5030182fb3a219cd370e.zip
ElGamal funktioniert und ist default
-rw-r--r--cipher/elgamal.c269
-rw-r--r--cipher/elgamal.h26
-rw-r--r--cipher/primegen.c17
-rw-r--r--cipher/rsa.c8
-rw-r--r--doc/DETAILS7
-rw-r--r--g10/Makefile.am1
-rw-r--r--g10/Makefile.in15
-rw-r--r--g10/build-packet.c43
-rw-r--r--g10/checksig.c96
-rw-r--r--g10/encode.c29
-rw-r--r--g10/free-packet.c91
-rw-r--r--g10/g10.c2
-rw-r--r--g10/getkey.c43
-rw-r--r--g10/keydb.h7
-rw-r--r--g10/keygen.c129
-rw-r--r--g10/keyid.c88
-rw-r--r--g10/main.h12
-rw-r--r--g10/mainproc.c33
-rw-r--r--g10/packet.h61
-rw-r--r--g10/parse-packet.c121
-rw-r--r--g10/pubkey-enc.c55
-rw-r--r--g10/seckey-cert.c102
-rw-r--r--g10/seskey.c47
-rw-r--r--g10/sig-check.c280
-rw-r--r--include/cipher.h33
-rw-r--r--include/mpi.h6
-rw-r--r--mpi/mpi-add.c14
-rw-r--r--mpi/mpi-inv.c2
-rw-r--r--mpi/mpi-mul.c7
-rw-r--r--tools/mpicalc.c2
-rw-r--r--util/logger.c10
31 files changed, 1260 insertions, 396 deletions
diff --git a/cipher/elgamal.c b/cipher/elgamal.c
index 305e1db92..b1239732d 100644
--- a/cipher/elgamal.c
+++ b/cipher/elgamal.c
@@ -28,34 +28,279 @@
#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;
+}
diff --git a/cipher/elgamal.h b/cipher/elgamal.h
index 3b6317599..e93b49e59 100644
--- a/cipher/elgamal.h
+++ b/cipher/elgamal.h
@@ -23,23 +23,27 @@
#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*/
diff --git a/cipher/primegen.c b/cipher/primegen.c
index 07d83d831..0173b3d0b 100644
--- a/cipher/primegen.c
+++ b/cipher/primegen.c
@@ -29,13 +29,26 @@
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(;;) {
diff --git a/cipher/rsa.c b/cipher/rsa.c
index b2694ed5e..a1f08457b 100644
--- a/cipher/rsa.c
+++ b/cipher/rsa.c
@@ -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
index 000000000..3b447c79b
--- /dev/null
+++ b/doc/DETAILS
@@ -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
+
+
diff --git a/g10/Makefile.am b/g10/Makefile.am
index a8d13eaec..bb0b96552 100644
--- a/g10/Makefile.am
+++ b/g10/Makefile.am
@@ -21,6 +21,7 @@ g10_SOURCES = g10.c \
cipher.c \
options.h \
openfile.c \
+ keyid.c \
packet.h \
parse-packet.c \
passphrase.c \
diff --git a/g10/Makefile.in b/g10/Makefile.in
index d7b08551d..651fdf2dd 100644
--- a/g10/Makefile.in
+++ b/g10/Makefile.in
@@ -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)
diff --git a/g10/build-packet.c b/g10/build-packet.c
index 5bda607b9..c0ddb9e24 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -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
index 7f00d5801..000000000
--- a/g10/checksig.c
+++ /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;
-}
-
-
diff --git a/g10/encode.c b/g10/encode.c
index 9ef2c1099..eb4875de9 100644
--- a/g10/encode.c
+++ b/g10/encode.c
@@ -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;
diff --git a/g10/free-packet.c b/g10/free-packet.c
index 7d6eb4aaa..3103ee49e 100644
--- a/g10/free-packet.c
+++ b/g10/free-packet.c
@@ -35,22 +35,39 @@
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;
}
diff --git a/g10/g10.c b/g10/g10.c
index 496fda348..5235d0f6e 100644
--- 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;
diff --git a/g10/getkey.c b/g10/getkey.c
index 8ca462210..4aea8e7ca 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -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 );
}
}
}
diff --git a/g10/keydb.h b/g10/keydb.h
index 62c6abe36..ae3aeb83f 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -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 );
diff --git a/g10/keygen.c b/g10/keygen.c
index 866824c1c..ff3715999 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -31,6 +31,13 @@
#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
index 000000000..0e2dad93b
--- /dev/null
+++ b/g10/keyid.c
@@ -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;
+}
+
+
diff --git a/g10/main.h b/g10/main.h
index 9d0f07a89..708563427 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -21,6 +21,11 @@
#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*/
diff --git a/g10/mainproc.c b/g10/mainproc.c
index 45cb8fbbd..6c7e32f3c 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -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 )) ) {
diff --git a/g10/packet.h b/g10/packet.h
index f57dce172..480fb54db 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -28,16 +28,22 @@
#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;
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index 35fc6d766..569657c29 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -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 ) {
diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c
index 93bdff9da..58da1aef8 100644
--- a/g10/pubkey-enc.c
+++ b/g10/pubkey-enc.c
@@ -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;
}
diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c
index c103de5c7..4e1a384c2 100644
--- a/g10/seckey-cert.c
+++ b/g10/seckey-cert.c
@@ -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;
+}
diff --git a/g10/seskey.c b/g10/seskey.c
index 317623ec8..5e944760d 100644
--- a/g10/seskey.c
+++ b/g10/seskey.c
@@ -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;
+}
+
diff --git a/g10/sig-check.c b/g10/sig-check.c
index 75e800693..ff212585c 100644
--- a/g10/sig-check.c
+++ b/g10/sig-check.c
@@ -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;
}
diff --git a/include/cipher.h b/include/cipher.h
index e178b5f4e..e3280428f 100644
--- a/include/cipher.h
+++ b/include/cipher.h
@@ -38,20 +38,27 @@
#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*/
diff --git a/include/mpi.h b/include/mpi.h
index 096cffec9..25fa696c4 100644
--- a/include/mpi.h
+++ b/include/mpi.h
@@ -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*/
diff --git a/mpi/mpi-add.c b/mpi/mpi-add.c
index 2c1aa6c61..b9c69af44 100644
--- a/mpi/mpi-add.c
+++ b/mpi/mpi-add.c
@@ -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 );
+}
+
diff --git a/mpi/mpi-inv.c b/mpi/mpi-inv.c
index f37f4e511..28cde00b6 100644
--- a/mpi/mpi-inv.c
+++ b/mpi/mpi-inv.c
@@ -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;
diff --git a/mpi/mpi-mul.c b/mpi/mpi-mul.c
index 03f2b4b44..aa5beb73b 100644
--- a/mpi/mpi-mul.c
+++ b/mpi/mpi-mul.c
@@ -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 );
+}
+
diff --git a/tools/mpicalc.c b/tools/mpicalc.c
index 828b475b3..28c498548 100644
--- a/tools/mpicalc.c
+++ b/tools/mpicalc.c
@@ -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--;
diff --git a/util/logger.c b/util/logger.c
index 9c1b86b23..8993ba43d 100644
--- a/util/logger.c
+++ b/util/logger.c
@@ -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();
}