mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
ElGamal funktioniert und ist default
This commit is contained in:
parent
a51cca90b6
commit
46900fbd43
273
cipher/elgamal.c
273
cipher/elgamal.c
@ -28,34 +28,279 @@
|
||||
#include <string.h>
|
||||
#include "util.h"
|
||||
#include "mpi.h"
|
||||
#include "cipher.h"
|
||||
#include "elgamal.h"
|
||||
|
||||
|
||||
/****************
|
||||
* 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.
|
||||
*/
|
||||
void
|
||||
elg_public(MPI output, MPI input, ELG_public_key *pkey )
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* 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;
|
||||
}
|
||||
|
||||
/****************
|
||||
* 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.
|
||||
* Generate a key pair with a key of size NBITS
|
||||
* Returns: 2 structures filles with all needed values
|
||||
*/
|
||||
void
|
||||
elg_secret(MPI output, MPI input, ELG_secret_key *skey )
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* 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_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;
|
||||
}
|
||||
|
||||
|
@ -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*/
|
||||
|
@ -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(;;) {
|
||||
|
@ -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 );
|
||||
|
7
doc/DETAILS
Normal file
7
doc/DETAILS
Normal file
@ -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
|
||||
|
||||
|
@ -21,6 +21,7 @@ g10_SOURCES = g10.c \
|
||||
cipher.c \
|
||||
options.h \
|
||||
openfile.c \
|
||||
keyid.c \
|
||||
packet.h \
|
||||
parse-packet.c \
|
||||
passphrase.c \
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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] );
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
29
g10/encode.c
29
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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
43
g10/getkey.c
43
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 )) )
|
||||
if( (rc = check_secret_key( skc )) )
|
||||
goto leave;
|
||||
if( skc.pubkey_algo != PUBKEY_ALGO_RSA ) {
|
||||
rc = G10ERR_PUBKEY_ALGO; /* unsupport algorithm */
|
||||
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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 );
|
||||
|
||||
|
||||
|
||||
|
129
g10/keygen.c
129
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);
|
||||
|
88
g10/keyid.c
Normal file
88
g10/keyid.c
Normal file
@ -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;
|
||||
}
|
||||
|
||||
|
12
g10/main.h
12
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*/
|
||||
|
@ -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 )) ) {
|
||||
|
61
g10/packet.h
61
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;
|
||||
|
||||
|
@ -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 ) {
|
||||
|
@ -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 ) {
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
/* get the secret key for the given public key
|
||||
* and decode the rsa_integer
|
||||
*/
|
||||
if( (rc = get_seckey( skey, k->keyid )) )
|
||||
goto leave;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
if( cert->pubkey_algo != PUBKEY_ALGO_RSA )
|
||||
return G10ERR_PUBKEY_ALGO; /* unsupport algorithm */
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
47
g10/seskey.c
47
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;
|
||||
}
|
||||
|
||||
|
302
g10/sig-check.c
302
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,11 +51,168 @@ signature_check( PKT_signature *sig, MD_HANDLE digest )
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
||||
if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
|
||||
ELG_public_key pkey;
|
||||
|
||||
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( 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;
|
||||
}
|
||||
else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
||||
RSA_public_key pkey;
|
||||
|
||||
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 );
|
||||
|
||||
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;
|
||||
else if( j == 19 && c == 0 ) {
|
||||
old_enc++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( old_enc ) {
|
||||
log_error("old encoding scheme is not supported\n");
|
||||
rc = G10ERR_GENERAL;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if( 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;
|
||||
}
|
||||
|
||||
/* 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 };
|
||||
|
||||
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 {
|
||||
log_debug("signature_check: unsupported pubkey algo %d\n",
|
||||
@ -64,148 +222,10 @@ signature_check( PKT_signature *sig, MD_HANDLE digest )
|
||||
}
|
||||
|
||||
|
||||
/* 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;
|
||||
}
|
||||
else if( ++j == 18 && c != 1 )
|
||||
break;
|
||||
else if( j == 19 && c == 0 ) {
|
||||
old_enc++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( old_enc ) {
|
||||
log_error("old encoding scheme is not supported\n");
|
||||
rc = G10ERR_GENERAL;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if( 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;
|
||||
}
|
||||
|
||||
/* 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 };
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
leave:
|
||||
mpi_free( result );
|
||||
if( pkc )
|
||||
free_pubkey_cert( pkc );
|
||||
mpi_free( result );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -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*/
|
||||
|
@ -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*/
|
||||
|
@ -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 );
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 );
|
||||
}
|
||||
|
||||
|
@ -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--;
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user