mirror of
git://git.gnupg.org/gnupg.git
synced 2025-04-12 22:11:29 +02: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 <string.h>
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "mpi.h"
|
#include "mpi.h"
|
||||||
|
#include "cipher.h"
|
||||||
#include "elgamal.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
|
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.
|
* Generate a key pair with a key of size NBITS
|
||||||
*
|
* Returns: 2 structures filles with all needed values
|
||||||
*
|
|
||||||
*
|
|
||||||
* Where m is OUTPUT, c is INPUT and d,n are elements of PKEY.
|
|
||||||
*/
|
*/
|
||||||
void
|
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"
|
#include "mpi.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
MPI e; /* exponent */
|
MPI p; /* prime */
|
||||||
MPI n; /* modulus */
|
MPI g; /* group generator */
|
||||||
|
MPI y; /* g^x mod p */
|
||||||
} ELG_public_key;
|
} ELG_public_key;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
MPI e; /* public exponent */
|
MPI p; /* prime */
|
||||||
MPI n; /* public modulus */
|
MPI g; /* group generator */
|
||||||
MPI p; /* prime p. */
|
MPI y; /* g^x mod p */
|
||||||
MPI q; /* prime q. */
|
MPI x; /* secret exponent */
|
||||||
MPI d; /* exponent */
|
|
||||||
MPI u; /* inverse of p mod q. */
|
|
||||||
} ELG_secret_key;
|
} ELG_secret_key;
|
||||||
|
|
||||||
|
|
||||||
void elg_public(MPI output, MPI input, ELG_public_key *skey );
|
void elg_free_public_key( ELG_public_key *pk );
|
||||||
void elg_secret(MPI output, MPI input, ELG_secret_key *skey );
|
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*/
|
#endif /*G10_ELGAMAL_H*/
|
||||||
|
@ -29,13 +29,26 @@
|
|||||||
|
|
||||||
static int no_of_small_prime_numbers;
|
static int no_of_small_prime_numbers;
|
||||||
static int rabin_miller( MPI n );
|
static int rabin_miller( MPI n );
|
||||||
|
static MPI gen_prime( unsigned nbits, int mode );
|
||||||
|
|
||||||
|
|
||||||
/****************
|
/****************
|
||||||
* Generate a prime number (stored in secure memory)
|
* Generate a prime number (stored in secure memory)
|
||||||
*/
|
*/
|
||||||
MPI
|
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;
|
unsigned nlimbs;
|
||||||
@ -61,7 +74,7 @@ generate_random_prime( unsigned nbits )
|
|||||||
val_3 = mpi_alloc( nlimbs );
|
val_3 = mpi_alloc( nlimbs );
|
||||||
mpi_set_ui(val_3, 3);
|
mpi_set_ui(val_3, 3);
|
||||||
result = mpi_alloc( nlimbs );
|
result = mpi_alloc( nlimbs );
|
||||||
prime = mpi_alloc_secure( nlimbs );
|
prime = secret? mpi_alloc_secure( nlimbs ): mpi_alloc( nlimbs );
|
||||||
count1 = count2 = 0;
|
count1 = count2 = 0;
|
||||||
/* enter (endless) loop */
|
/* enter (endless) loop */
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
@ -95,8 +95,8 @@ rsa_generate( RSA_public_key *pk, RSA_secret_key *sk, unsigned nbits )
|
|||||||
MPI f;
|
MPI f;
|
||||||
|
|
||||||
/* select two (very secret) primes */
|
/* select two (very secret) primes */
|
||||||
p = generate_random_prime( nbits / 2 );
|
p = generate_secret_prime( nbits / 2 );
|
||||||
q = generate_random_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)*/
|
if( mpi_cmp( p, q ) > 0 ) /* p shall be smaller than q (for calc of u)*/
|
||||||
mpi_swap(p,q);
|
mpi_swap(p,q);
|
||||||
/* calculate Euler totient: phi = (p-1)(q-1) */
|
/* 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);
|
mpi_add_ui( e, e, 2);
|
||||||
/* calculate the secret key d = e^1 mod phi */
|
/* calculate the secret key d = e^1 mod phi */
|
||||||
d = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
|
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)*/
|
/* calculate the inverse of p and q (used for chinese remainder theorem)*/
|
||||||
u = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
|
u = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
|
||||||
mpi_inv_mod(u, p, q );
|
mpi_invm(u, p, q );
|
||||||
|
|
||||||
if( DBG_CIPHER ) {
|
if( DBG_CIPHER ) {
|
||||||
log_mpidump(" p= ", p );
|
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 \
|
cipher.c \
|
||||||
options.h \
|
options.h \
|
||||||
openfile.c \
|
openfile.c \
|
||||||
|
keyid.c \
|
||||||
packet.h \
|
packet.h \
|
||||||
parse-packet.c \
|
parse-packet.c \
|
||||||
passphrase.c \
|
passphrase.c \
|
||||||
|
@ -59,6 +59,7 @@ g10_SOURCES = g10.c \
|
|||||||
cipher.c \
|
cipher.c \
|
||||||
options.h \
|
options.h \
|
||||||
openfile.c \
|
openfile.c \
|
||||||
|
keyid.c \
|
||||||
packet.h \
|
packet.h \
|
||||||
parse-packet.c \
|
parse-packet.c \
|
||||||
passphrase.c \
|
passphrase.c \
|
||||||
@ -90,7 +91,7 @@ COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
|
|||||||
LINK = $(CC) $(LDFLAGS) -o $@
|
LINK = $(CC) $(LDFLAGS) -o $@
|
||||||
g10_OBJECTS = g10.o build-packet.o compress.o encode.o encr-data.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 \
|
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
|
seckey-cert.o seskey.o sign.o comment.o sig-check.o
|
||||||
EXTRA_g10_SOURCES =
|
EXTRA_g10_SOURCES =
|
||||||
g10_LDADD = $(LDADD)
|
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/compress.P $(srcdir)/.deps/encode.P \
|
||||||
$(srcdir)/.deps/encr-data.P $(srcdir)/.deps/free-packet.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/g10.P $(srcdir)/.deps/getkey.P $(srcdir)/.deps/keygen.P \
|
||||||
$(srcdir)/.deps/mainproc.P $(srcdir)/.deps/mdfilter.P \
|
$(srcdir)/.deps/keyid.P $(srcdir)/.deps/mainproc.P \
|
||||||
$(srcdir)/.deps/openfile.P $(srcdir)/.deps/parse-packet.P \
|
$(srcdir)/.deps/mdfilter.P $(srcdir)/.deps/openfile.P \
|
||||||
$(srcdir)/.deps/passphrase.P $(srcdir)/.deps/plaintext.P \
|
$(srcdir)/.deps/parse-packet.P $(srcdir)/.deps/passphrase.P \
|
||||||
$(srcdir)/.deps/pubkey-enc.P $(srcdir)/.deps/seckey-cert.P \
|
$(srcdir)/.deps/plaintext.P $(srcdir)/.deps/pubkey-enc.P \
|
||||||
$(srcdir)/.deps/seskey.P $(srcdir)/.deps/sig-check.P \
|
$(srcdir)/.deps/seckey-cert.P $(srcdir)/.deps/seskey.P \
|
||||||
$(srcdir)/.deps/sign.P
|
$(srcdir)/.deps/sig-check.P $(srcdir)/.deps/sign.P
|
||||||
SOURCES = $(g10_SOURCES)
|
SOURCES = $(g10_SOURCES)
|
||||||
OBJECTS = $(g10_OBJECTS)
|
OBJECTS = $(g10_OBJECTS)
|
||||||
|
|
||||||
|
@ -163,7 +163,12 @@ do_pubkey_cert( IOBUF out, int ctb, PKT_pubkey_cert *pkc )
|
|||||||
write_32(a, pkc->timestamp );
|
write_32(a, pkc->timestamp );
|
||||||
write_16(a, pkc->valid_days );
|
write_16(a, pkc->valid_days );
|
||||||
iobuf_put(a, pkc->pubkey_algo );
|
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_n );
|
||||||
mpi_encode(a, pkc->d.rsa.rsa_e );
|
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_32(a, skc->timestamp );
|
||||||
write_16(a, skc->valid_days );
|
write_16(a, skc->valid_days );
|
||||||
iobuf_put(a, skc->pubkey_algo );
|
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_n );
|
||||||
mpi_encode(a, skc->d.rsa.rsa_e );
|
mpi_encode(a, skc->d.rsa.rsa_e );
|
||||||
iobuf_put(a, skc->d.rsa.protect_algo );
|
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[0] );
|
||||||
write_32(a, enc->keyid[1] );
|
write_32(a, enc->keyid[1] );
|
||||||
iobuf_put(a,enc->pubkey_algo );
|
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 );
|
mpi_encode(a, enc->d.rsa.rsa_integer );
|
||||||
}
|
}
|
||||||
else {
|
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[0] );
|
||||||
write_32(a, sig->keyid[1] );
|
write_32(a, sig->keyid[1] );
|
||||||
iobuf_put(a, sig->pubkey_algo );
|
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_algo );
|
||||||
iobuf_put(a, sig->d.rsa.digest_start[0] );
|
iobuf_put(a, sig->d.rsa.digest_start[0] );
|
||||||
iobuf_put(a, sig->d.rsa.digest_start[1] );
|
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 */
|
/* build the pubkey packet */
|
||||||
enc = m_alloc_clear( sizeof *enc );
|
enc = m_alloc_clear( sizeof *enc );
|
||||||
enc->pubkey_algo = pkc->pubkey_algo;
|
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;
|
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,
|
enc->d.rsa.rsa_integer = encode_session_key( cfx.dek,
|
||||||
mpi_get_nbits(pkc->d.rsa.rsa_n) );
|
mpi_get_nbits(pkc->d.rsa.rsa_n) );
|
||||||
pkey.n = pkc->d.rsa.rsa_n;
|
pkey.n = pkc->d.rsa.rsa_n;
|
||||||
|
@ -35,22 +35,39 @@
|
|||||||
void
|
void
|
||||||
free_pubkey_enc( PKT_pubkey_enc *enc )
|
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);
|
m_free(enc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
free_seckey_enc( PKT_signature *enc )
|
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);
|
m_free(enc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
free_pubkey_cert( PKT_pubkey_cert *cert )
|
free_pubkey_cert( PKT_pubkey_cert *cert )
|
||||||
{
|
{
|
||||||
mpi_free( cert->d.rsa.rsa_n );
|
if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
|
||||||
mpi_free( cert->d.rsa.rsa_e );
|
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 );
|
md5_close( cert->mfx.md5 );
|
||||||
rmd160_close( cert->mfx.rmd160 );
|
rmd160_close( cert->mfx.rmd160 );
|
||||||
m_free(cert);
|
m_free(cert);
|
||||||
@ -62,8 +79,15 @@ copy_pubkey_cert( PKT_pubkey_cert *d, PKT_pubkey_cert *s )
|
|||||||
if( !d )
|
if( !d )
|
||||||
d = m_alloc(sizeof *d);
|
d = m_alloc(sizeof *d);
|
||||||
memcpy( d, s, sizeof *d );
|
memcpy( d, s, sizeof *d );
|
||||||
d->d.rsa.rsa_n = mpi_copy( s->d.rsa.rsa_n );
|
if( s->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
|
||||||
d->d.rsa.rsa_e = mpi_copy( s->d.rsa.rsa_e );
|
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.md5 = NULL;
|
||||||
d->mfx.rmd160 =NULL;
|
d->mfx.rmd160 =NULL;
|
||||||
return d;
|
return d;
|
||||||
@ -72,19 +96,30 @@ copy_pubkey_cert( PKT_pubkey_cert *d, PKT_pubkey_cert *s )
|
|||||||
void
|
void
|
||||||
free_seckey_cert( PKT_seckey_cert *cert )
|
free_seckey_cert( PKT_seckey_cert *cert )
|
||||||
{
|
{
|
||||||
mpi_free( cert->d.rsa.rsa_n );
|
if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
|
||||||
mpi_free( cert->d.rsa.rsa_e );
|
mpi_free( cert->d.elg.p );
|
||||||
if( cert->d.rsa.is_protected ) {
|
mpi_free( cert->d.elg.g );
|
||||||
m_free( cert->d.rsa.rsa_d );
|
mpi_free( cert->d.elg.y );
|
||||||
m_free( cert->d.rsa.rsa_p );
|
if( cert->d.rsa.is_protected )
|
||||||
m_free( cert->d.rsa.rsa_q );
|
m_free( cert->d.elg.x );
|
||||||
m_free( cert->d.rsa.rsa_u );
|
else
|
||||||
|
mpi_free( cert->d.elg.x );
|
||||||
}
|
}
|
||||||
else {
|
else if( cert->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
||||||
mpi_free( cert->d.rsa.rsa_d );
|
mpi_free( cert->d.rsa.rsa_n );
|
||||||
mpi_free( cert->d.rsa.rsa_p );
|
mpi_free( cert->d.rsa.rsa_e );
|
||||||
mpi_free( cert->d.rsa.rsa_q );
|
if( cert->d.rsa.is_protected ) {
|
||||||
mpi_free( cert->d.rsa.rsa_u );
|
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);
|
m_free(cert);
|
||||||
}
|
}
|
||||||
@ -95,12 +130,20 @@ copy_seckey_cert( PKT_seckey_cert *d, PKT_seckey_cert *s )
|
|||||||
if( !d )
|
if( !d )
|
||||||
d = m_alloc(sizeof *d);
|
d = m_alloc(sizeof *d);
|
||||||
memcpy( d, s, sizeof *d );
|
memcpy( d, s, sizeof *d );
|
||||||
d->d.rsa.rsa_n = mpi_copy( s->d.rsa.rsa_n );
|
if( s->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
|
||||||
d->d.rsa.rsa_e = mpi_copy( s->d.rsa.rsa_e );
|
d->d.elg.p = mpi_copy( s->d.elg.p );
|
||||||
d->d.rsa.rsa_d = mpi_copy( s->d.rsa.rsa_d );
|
d->d.elg.g = mpi_copy( s->d.elg.g );
|
||||||
d->d.rsa.rsa_p = mpi_copy( s->d.rsa.rsa_p );
|
d->d.elg.y = mpi_copy( s->d.elg.y );
|
||||||
d->d.rsa.rsa_q = mpi_copy( s->d.rsa.rsa_q );
|
d->d.elg.x = mpi_copy( s->d.elg.x );
|
||||||
d->d.rsa.rsa_u = mpi_copy( s->d.rsa.rsa_u );
|
}
|
||||||
|
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;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ main( int argc, char **argv )
|
|||||||
case aPrimegen:
|
case aPrimegen:
|
||||||
if( argc )
|
if( argc )
|
||||||
usage(1);
|
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');
|
putchar('\n');
|
||||||
break;
|
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;
|
pkc_cache_entry_t ce;
|
||||||
u32 keyid[2];
|
u32 keyid[2];
|
||||||
|
|
||||||
if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL
|
||||||
mpi_get_keyid( pkc->d.rsa.rsa_n, keyid );
|
|| pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
||||||
|
keyid_from_pkc( pkc, keyid );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return; /* don't know how to get the keyid */
|
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
|
* Get a secret key and store it into skey
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
get_seckey( RSA_secret_key *skey, u32 *keyid )
|
get_seckey( PKT_seckey_cert *skc, u32 *keyid )
|
||||||
{
|
{
|
||||||
int rc=0;
|
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;
|
goto found;
|
||||||
/* fixme: look at other places */
|
/* fixme: look at other places */
|
||||||
goto leave;
|
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
|
/* get the secret key (this may prompt for a passprase to
|
||||||
* unlock the secret key
|
* unlock the secret key
|
||||||
*/
|
*/
|
||||||
if( (rc = check_secret_key( &skc )) )
|
if( (rc = check_secret_key( skc )) )
|
||||||
goto leave;
|
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:
|
leave:
|
||||||
memset( &skc, 0, sizeof skc );
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,8 +344,9 @@ scan_keyring( PKT_pubkey_cert *pkc, u32 *keyid,
|
|||||||
}
|
}
|
||||||
else if( keyid && pkt.pkttype == PKT_PUBKEY_CERT ) {
|
else if( keyid && pkt.pkttype == PKT_PUBKEY_CERT ) {
|
||||||
switch( pkt.pkt.pubkey_cert->pubkey_algo ) {
|
switch( pkt.pkt.pubkey_cert->pubkey_algo ) {
|
||||||
|
case PUBKEY_ALGO_ELGAMAL:
|
||||||
case PUBKEY_ALGO_RSA:
|
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] ) {
|
if( akeyid[0] == keyid[0] && akeyid[1] == keyid[1] ) {
|
||||||
copy_pubkey_cert( pkc, pkt.pkt.pubkey_cert );
|
copy_pubkey_cert( pkc, pkt.pkt.pubkey_cert );
|
||||||
found++;
|
found++;
|
||||||
@ -406,8 +394,9 @@ scan_keyring( PKT_pubkey_cert *pkc, u32 *keyid,
|
|||||||
log_error("Ooops: no pubkey for userid '%.*s'\n",
|
log_error("Ooops: no pubkey for userid '%.*s'\n",
|
||||||
pkt.pkt.user_id->len, pkt.pkt.user_id->name);
|
pkt.pkt.user_id->len, pkt.pkt.user_id->name);
|
||||||
else {
|
else {
|
||||||
if( last_pk->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
if( last_pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL
|
||||||
mpi_get_keyid( last_pk->d.rsa.rsa_n , akeyid );
|
|| last_pk->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
||||||
|
keyid_from_pkc( last_pk, akeyid );
|
||||||
cache_user_id( pkt.pkt.user_id, akeyid );
|
cache_user_id( pkt.pkt.user_id, akeyid );
|
||||||
}
|
}
|
||||||
cache_pubkey_cert( last_pk );
|
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 ) {
|
else if( keyid && pkt.pkttype == PKT_SECKEY_CERT ) {
|
||||||
switch( pkt.pkt.seckey_cert->pubkey_algo ) {
|
switch( pkt.pkt.seckey_cert->pubkey_algo ) {
|
||||||
|
case PUBKEY_ALGO_ELGAMAL:
|
||||||
case PUBKEY_ALGO_RSA:
|
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] ) {
|
if( akeyid[0] == keyid[0] && akeyid[1] == keyid[1] ) {
|
||||||
copy_seckey_cert( skc, pkt.pkt.seckey_cert );
|
copy_seckey_cert( skc, pkt.pkt.seckey_cert );
|
||||||
found++;
|
found++;
|
||||||
@ -510,9 +500,10 @@ scan_secret_keyring( PKT_seckey_cert *skc, u32 *keyid,
|
|||||||
log_error("Ooops: no seckey for userid '%.*s'\n",
|
log_error("Ooops: no seckey for userid '%.*s'\n",
|
||||||
pkt.pkt.user_id->len, pkt.pkt.user_id->name);
|
pkt.pkt.user_id->len, pkt.pkt.user_id->name);
|
||||||
else {
|
else {
|
||||||
if( last_pk->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
if( last_pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL
|
||||||
mpi_get_keyid( last_pk->d.rsa.rsa_n , akeyid );
|
|| last_pk->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
||||||
cache_user_id( pkt.pkt.user_id, akeyid );
|
keyid_from_skc( last_pk, akeyid );
|
||||||
|
cache_user_id( pkt.pkt.user_id, akeyid );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#define G10_KEYDB_H
|
#define G10_KEYDB_H
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include "packet.h"
|
||||||
#include "cipher.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 );
|
void cache_user_id( PKT_user_id *uid, u32 *keyid );
|
||||||
int get_pubkey( PKT_pubkey_cert *pkc, 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_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 );
|
int get_seckey_by_name( PKT_seckey_cert *skc, const char *name );
|
||||||
char*get_user_id_string( u32 *keyid );
|
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 "ttyio.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define TEST_ALGO 1
|
||||||
|
#define TEST_NBITS 256
|
||||||
|
#define TEST_UID "Karl Test"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
answer_is_yes( const char *s )
|
answer_is_yes( const char *s )
|
||||||
{
|
{
|
||||||
@ -62,6 +69,7 @@ write_uid( IOBUF out, const char *s )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_RSA_CIPHER
|
||||||
static int
|
static int
|
||||||
gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
|
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);
|
free_packet(&pkt2);
|
||||||
return rc;
|
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 pub_io = NULL;
|
||||||
IOBUF sec_io = NULL;
|
IOBUF sec_io = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
|
int algo;
|
||||||
|
const char *algo_name;
|
||||||
|
|
||||||
|
#ifndef TEST_ALGO
|
||||||
if( opt.batch || opt.answer_yes || opt.answer_no )
|
if( opt.batch || opt.answer_yes || opt.answer_no )
|
||||||
log_fatal("Key generation can only be used in interactive mode\n");
|
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"
|
" minimum keysize is 768 bits\n"
|
||||||
" default keysize is 1024 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(;;) {
|
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();
|
tty_kill_prompt();
|
||||||
nbits = *answer? atoi(answer): 256;
|
nbits = *answer? atoi(answer): 1024;
|
||||||
m_free(answer);
|
m_free(answer);
|
||||||
|
#endif
|
||||||
if( nbits < 128 ) /* FIXME: change this to 768 */
|
if( nbits < 128 ) /* FIXME: change this to 768 */
|
||||||
tty_printf("keysize too small; please select a larger one\n");
|
tty_printf("keysize too small; please select a larger one\n");
|
||||||
else if( nbits > 2048 ) {
|
else if( nbits > 2048 ) {
|
||||||
@ -167,6 +273,11 @@ generate_keypair()
|
|||||||
nbits = ((nbits + 31) / 32) * 32;
|
nbits = ((nbits + 31) / 32) * 32;
|
||||||
tty_printf("rounded up to %u bits\n", nbits );
|
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"
|
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"
|
"email address in this suggested format:\n"
|
||||||
" \"Heinrich Heine <heinrichh@uni-duesseldorf.de>\n" );
|
" \"Heinrich Heine <heinrichh@uni-duesseldorf.de>\n" );
|
||||||
@ -189,6 +300,7 @@ generate_keypair()
|
|||||||
m_free(answer);
|
m_free(answer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/* now check wether we a are allowed to write the keyrings */
|
/* now check wether we a are allowed to write the keyrings */
|
||||||
if( !(rc=overwrite_filep( pub_fname )) ) {
|
if( !(rc=overwrite_filep( pub_fname )) ) {
|
||||||
if( !(pub_io = iobuf_create( 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( pub_io, "#public key created by G10 pre-release " VERSION );
|
||||||
write_comment( sec_io, "#secret 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(pub_io, uid );
|
||||||
write_uid(sec_io, uid );
|
write_uid(sec_io, uid );
|
||||||
m_free(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
|
#define G10_MAIN_H
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "iobuf.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 --*/
|
/*-- encode.c --*/
|
||||||
int encode_symmetric( const char *filename );
|
int encode_symmetric( const char *filename );
|
||||||
@ -37,4 +42,11 @@ void generate_keypair(void);
|
|||||||
int overwrite_filep( const char *fname );
|
int overwrite_filep( const char *fname );
|
||||||
IOBUF open_outfile( 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*/
|
#endif /*G10_MAIN_H*/
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "cipher.h"
|
#include "cipher.h"
|
||||||
#include "keydb.h"
|
#include "keydb.h"
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
static int opt_list=1; /* and list the data packets to stdout */
|
static int opt_list=1; /* and list the data packets to stdout */
|
||||||
|
|
||||||
@ -122,8 +123,9 @@ proc_packets( IOBUF a )
|
|||||||
puts(" (orphaned)");
|
puts(" (orphaned)");
|
||||||
}
|
}
|
||||||
if( pkt->pkc_parent ) {
|
if( pkt->pkc_parent ) {
|
||||||
if( pkt->pkc_parent->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
if( pkt->pkc_parent->pubkey_algo == PUBKEY_ALGO_ELGAMAL
|
||||||
mpi_get_keyid( pkt->pkc_parent->d.rsa.rsa_n, keyid );
|
|| pkt->pkc_parent->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
||||||
|
keyid_from_pkc( pkt->pkc_parent, keyid );
|
||||||
cache_user_id( pkt->pkt.user_id, keyid );
|
cache_user_id( pkt->pkt.user_id, keyid );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -158,6 +160,30 @@ proc_packets( IOBUF a )
|
|||||||
result = -1;
|
result = -1;
|
||||||
printstr(lvl0, "sig: from %s\n", ustr );
|
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 ) {
|
else if(sig->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
||||||
md_handle.algo = sig->d.rsa.digest_algo;
|
md_handle.algo = sig->d.rsa.digest_algo;
|
||||||
if( sig->d.rsa.digest_algo == DIGEST_ALGO_RMD160 ) {
|
if( sig->d.rsa.digest_algo == DIGEST_ALGO_RMD160 ) {
|
||||||
@ -204,7 +230,8 @@ proc_packets( IOBUF a )
|
|||||||
enc = pkt->pkt.pubkey_enc;
|
enc = pkt->pkt.pubkey_enc;
|
||||||
printf("enc: encrypted by a pubkey with keyid %08lX\n",
|
printf("enc: encrypted by a pubkey with keyid %08lX\n",
|
||||||
enc->keyid[1] );
|
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 */
|
m_free(dek ); /* paranoid: delete a pending DEK */
|
||||||
dek = m_alloc_secure( sizeof *dek );
|
dek = m_alloc_secure( sizeof *dek );
|
||||||
if( (result = get_session_key( enc, dek )) ) {
|
if( (result = get_session_key( enc, dek )) ) {
|
||||||
|
61
g10/packet.h
61
g10/packet.h
@ -28,16 +28,22 @@
|
|||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
|
|
||||||
|
|
||||||
#define PKT_PUBKEY_ENC 1 /* public key encrypted packet */
|
#define PKT_PUBKEY_ENC 1 /* public key encrypted packet */
|
||||||
#define PKT_SIGNATURE 2 /* secret key encrypted packet */
|
#define PKT_SIGNATURE 2 /* secret key encrypted packet */
|
||||||
#define PKT_SECKEY_CERT 5 /* secret key certificate */
|
#define PKT_SESSION_KEY 3 /* session key packet (OpenPGP)*/
|
||||||
#define PKT_PUBKEY_CERT 6 /* public key certificate */
|
#define PKT_ONEPASS_SIG 4 /* one pass sig packet (OpenPGP)*/
|
||||||
#define PKT_COMPR_DATA 8 /* compressed data packet */
|
#define PKT_SECKEY_CERT 5 /* secret key certificate */
|
||||||
#define PKT_ENCR_DATA 9 /* conventional encrypted data */
|
#define PKT_PUBKEY_CERT 6 /* public key certificate */
|
||||||
#define PKT_PLAINTEXT 11 /* plaintext data with filename and mode */
|
#define PKT_SECKEY_SUBCERT 7 /* secret subkey certificate (OpenPGP) */
|
||||||
#define PKT_RING_TRUST 12 /* keyring trust packet */
|
#define PKT_COMPR_DATA 8 /* compressed data packet */
|
||||||
#define PKT_USER_ID 13 /* user id packet */
|
#define PKT_ENCR_DATA 9 /* conventional encrypted data */
|
||||||
#define PKT_COMMENT 14 /* comment packet */
|
#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;
|
typedef struct packet_struct PACKET;
|
||||||
|
|
||||||
@ -48,6 +54,9 @@ typedef struct {
|
|||||||
struct {
|
struct {
|
||||||
MPI rsa_integer; /* integer containing the DEK */
|
MPI rsa_integer; /* integer containing the DEK */
|
||||||
} rsa;
|
} rsa;
|
||||||
|
struct {
|
||||||
|
MPI a, b; /* integers with the enciphered DEK */
|
||||||
|
} elg;
|
||||||
} d;
|
} d;
|
||||||
} PKT_pubkey_enc;
|
} PKT_pubkey_enc;
|
||||||
|
|
||||||
@ -60,10 +69,15 @@ typedef struct {
|
|||||||
/* (PUBKEY_ALGO_xxx) */
|
/* (PUBKEY_ALGO_xxx) */
|
||||||
union {
|
union {
|
||||||
struct {
|
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 */
|
byte digest_start[2]; /* first 2 byte of the digest */
|
||||||
MPI rsa_integer; /* the encrypted digest */
|
MPI rsa_integer; /* the encrypted digest */
|
||||||
} rsa;
|
} 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;
|
} d;
|
||||||
} PKT_signature;
|
} PKT_signature;
|
||||||
|
|
||||||
@ -78,6 +92,11 @@ typedef struct {
|
|||||||
MPI rsa_n; /* public modulus */
|
MPI rsa_n; /* public modulus */
|
||||||
MPI rsa_e; /* public exponent */
|
MPI rsa_e; /* public exponent */
|
||||||
} rsa;
|
} rsa;
|
||||||
|
struct {
|
||||||
|
MPI p; /* prime */
|
||||||
|
MPI g; /* group generator */
|
||||||
|
MPI y; /* g^x mod p */
|
||||||
|
} elg;
|
||||||
} d;
|
} d;
|
||||||
} PKT_pubkey_cert;
|
} PKT_pubkey_cert;
|
||||||
|
|
||||||
@ -106,6 +125,24 @@ typedef struct {
|
|||||||
} blowfish;
|
} blowfish;
|
||||||
} protect;
|
} protect;
|
||||||
} rsa;
|
} 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;
|
} d;
|
||||||
} PKT_seckey_cert;
|
} PKT_seckey_cert;
|
||||||
|
|
||||||
|
@ -148,6 +148,7 @@ parse_packet( IOBUF inp, PACKET *pkt )
|
|||||||
rc = parse_certificate(inp, pkttype, pktlen, hdr, hdrlen, pkt );
|
rc = parse_certificate(inp, pkttype, pktlen, hdr, hdrlen, pkt );
|
||||||
break;
|
break;
|
||||||
case PKT_SECKEY_CERT:
|
case PKT_SECKEY_CERT:
|
||||||
|
case PKT_SECKEY_SUBCERT:
|
||||||
pkt->pkt.seckey_cert = m_alloc_clear(sizeof *pkt->pkt.seckey_cert );
|
pkt->pkt.seckey_cert = m_alloc_clear(sizeof *pkt->pkt.seckey_cert );
|
||||||
rc = parse_certificate(inp, pkttype, pktlen, hdr, hdrlen, pkt );
|
rc = parse_certificate(inp, pkttype, pktlen, hdr, hdrlen, pkt );
|
||||||
break;
|
break;
|
||||||
@ -230,7 +231,19 @@ parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
|
|||||||
if( list_mode )
|
if( list_mode )
|
||||||
printf(":public key packet: keyid %08lX%08lX\n",
|
printf(":public key packet: keyid %08lX%08lX\n",
|
||||||
k->keyid[0], k->keyid[1]);
|
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;
|
n = pktlen;
|
||||||
k->d.rsa.rsa_integer = mpi_decode(inp, &n ); pktlen -=n;
|
k->d.rsa.rsa_integer = mpi_decode(inp, &n ); pktlen -=n;
|
||||||
if( list_mode ) {
|
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",
|
"\tversion %d, created %lu, md5len %d, sigclass %02x\n",
|
||||||
sig->keyid[0], sig->keyid[1],
|
sig->keyid[0], sig->keyid[1],
|
||||||
version, sig->timestamp, md5_len, sig->sig_class );
|
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 ) {
|
if( pktlen < 5 ) {
|
||||||
log_error("packet(%d) too short\n", pkttype);
|
log_error("packet(%d) too short\n", pkttype);
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -315,7 +350,7 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
|
|||||||
unsigned n;
|
unsigned n;
|
||||||
unsigned long timestamp;
|
unsigned long timestamp;
|
||||||
unsigned short valid_period;
|
unsigned short valid_period;
|
||||||
MPI rsa_pub_mod, rsa_pub_exp;
|
int is_v4=0;
|
||||||
|
|
||||||
if( pkttype == PKT_PUBKEY_CERT ) {
|
if( pkttype == PKT_PUBKEY_CERT ) {
|
||||||
pkt->pkt.pubkey_cert->mfx.md5 = md5_open(0);
|
pkt->pkt.pubkey_cert->mfx.md5 = md5_open(0);
|
||||||
@ -331,13 +366,18 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
version = iobuf_get_noeof(inp); pktlen--;
|
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);
|
log_error("packet(%d) with unknown version %d\n", pkttype, version);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
timestamp = read_32(inp); pktlen -= 4;
|
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--;
|
algorithm = iobuf_get_noeof(inp); pktlen--;
|
||||||
if( list_mode )
|
if( list_mode )
|
||||||
printf(":%s key certification packet:\n"
|
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;
|
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_mod = mpi_decode(inp, &n ); pktlen -=n;
|
||||||
n = pktlen; rsa_pub_exp = mpi_decode(inp, &n ); pktlen -=n;
|
n = pktlen; rsa_pub_exp = mpi_decode(inp, &n ); pktlen -=n;
|
||||||
if( list_mode ) {
|
if( list_mode ) {
|
||||||
|
@ -39,24 +39,50 @@ int
|
|||||||
get_session_key( PKT_pubkey_enc *k, DEK *dek )
|
get_session_key( PKT_pubkey_enc *k, DEK *dek )
|
||||||
{
|
{
|
||||||
int i, j, c, rc = 0;
|
int i, j, c, rc = 0;
|
||||||
RSA_secret_key *skey = m_alloc_secure( sizeof *skey );
|
|
||||||
MPI dek_frame = mpi_alloc_secure(40);
|
MPI dek_frame = mpi_alloc_secure(40);
|
||||||
u16 csum, csum2;
|
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 */
|
rc = G10ERR_PUBKEY_ALGO; /* unsupported algorithm */
|
||||||
goto leave;
|
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
|
/* Now get the DEK (data encryption key) from the dek_frame
|
||||||
*
|
*
|
||||||
* Old versions encode the DEK in in this format (msb is left):
|
* 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 */
|
if( c != 2 ) /* somethink is wrong */
|
||||||
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
|
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
|
||||||
/* look for the zeor byte */
|
/* look for the zero byte */
|
||||||
for(i--; i > 4 ; i-- )
|
for(i--; i > 4 ; i-- )
|
||||||
if( !mpi_getbyte(dek_frame,i) )
|
if( !mpi_getbyte(dek_frame,i) )
|
||||||
break;
|
break;
|
||||||
@ -95,10 +121,10 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
|
|||||||
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
|
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
|
||||||
/* next byte indicates the used cipher */
|
/* next byte indicates the used cipher */
|
||||||
switch( mpi_getbyte(dek_frame, --i ) ) {
|
switch( mpi_getbyte(dek_frame, --i ) ) {
|
||||||
case 1:
|
case CIPHER_ALGO_IDEA:
|
||||||
rc = G10ERR_NI_CIPHER;
|
rc = G10ERR_NI_CIPHER;
|
||||||
goto leave;
|
goto leave;
|
||||||
case 42:
|
case CIPHER_ALGO_BLOWFISH:
|
||||||
if( i != 22 ) /* length of blowfish is 20 (+2 bytes checksum) */
|
if( i != 22 ) /* length of blowfish is 20 (+2 bytes checksum) */
|
||||||
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
|
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
|
||||||
dek->algo = CIPHER_ALGO_BLOWFISH;
|
dek->algo = CIPHER_ALGO_BLOWFISH;
|
||||||
@ -122,7 +148,8 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
|
|||||||
|
|
||||||
leave:
|
leave:
|
||||||
mpi_free(dek_frame);
|
mpi_free(dek_frame);
|
||||||
m_free(skey);
|
if( skc )
|
||||||
|
free_seckey_cert( skc );
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,9 @@
|
|||||||
#include "keydb.h"
|
#include "keydb.h"
|
||||||
#include "cipher.h"
|
#include "cipher.h"
|
||||||
|
|
||||||
|
#if BLOWFISH_BLOCKSIZE != 8
|
||||||
|
#error unsupportted blocksize
|
||||||
|
#endif
|
||||||
|
|
||||||
static u16
|
static u16
|
||||||
checksum( byte *p )
|
checksum( byte *p )
|
||||||
@ -44,11 +47,9 @@ checksum( byte *p )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Check the secret key certificate
|
static int
|
||||||
*/
|
check_elg( PKT_seckey_cert *cert )
|
||||||
int
|
|
||||||
check_secret_key( PKT_seckey_cert *cert )
|
|
||||||
{
|
{
|
||||||
byte iv[8];
|
byte iv[8];
|
||||||
byte *mpibuf;
|
byte *mpibuf;
|
||||||
@ -56,13 +57,73 @@ check_secret_key( PKT_seckey_cert *cert )
|
|||||||
MPI temp_mpi;
|
MPI temp_mpi;
|
||||||
int res;
|
int res;
|
||||||
u32 keyid[2];
|
u32 keyid[2];
|
||||||
|
ELG_secret_key skey;
|
||||||
|
|
||||||
#if BLOWFISH_BLOCKSIZE != 8
|
if( cert->d.elg.is_protected ) { /* remove the protection */
|
||||||
#error unsupportted blocksize
|
DEK *dek = NULL;
|
||||||
#endif
|
BLOWFISH_context *blowfish_ctx=NULL;
|
||||||
|
|
||||||
if( cert->pubkey_algo != PUBKEY_ALGO_RSA )
|
switch( cert->d.elg.protect_algo ) {
|
||||||
return G10ERR_PUBKEY_ALGO; /* unsupport algorithm */
|
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 */
|
if( cert->d.rsa.is_protected ) { /* remove the protection */
|
||||||
DEK *dek = NULL;
|
DEK *dek = NULL;
|
||||||
@ -73,7 +134,7 @@ check_secret_key( PKT_seckey_cert *cert )
|
|||||||
log_bug("unprotect seckey_cert is flagged protected\n");
|
log_bug("unprotect seckey_cert is flagged protected\n");
|
||||||
break;
|
break;
|
||||||
case CIPHER_ALGO_BLOWFISH:
|
case CIPHER_ALGO_BLOWFISH:
|
||||||
mpi_get_keyid( cert->d.rsa.rsa_n , keyid );
|
keyid_from_skc( cert, keyid );
|
||||||
dek = get_passphrase_hash( keyid, NULL );
|
dek = get_passphrase_hash( keyid, NULL );
|
||||||
|
|
||||||
m_free(dek); /* pw is in secure memory, so m_free() burns it */
|
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;
|
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 "util.h"
|
||||||
#include "cipher.h"
|
#include "cipher.h"
|
||||||
#include "mpi.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)
|
* 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes)
|
||||||
*
|
*
|
||||||
* RND are non-zero random 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
|
* DEK is the encryption key (session key) length k depends on the
|
||||||
* cipher algorithm (20 is used with blowfish).
|
* cipher algorithm (20 is used with blowfish).
|
||||||
* CSUM is the 16 bit checksum over the DEK
|
* CSUM is the 16 bit checksum over the DEK
|
||||||
@ -106,7 +107,7 @@ encode_session_key( DEK *dek, unsigned nbits )
|
|||||||
MPI
|
MPI
|
||||||
encode_rmd160_value( byte *md, unsigned len, unsigned nbits )
|
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,
|
{ 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48,
|
||||||
0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 };
|
0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 };
|
||||||
int nframe = (nbits+7) / 8;
|
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:
|
/* 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.
|
* PAD consists of FF bytes.
|
||||||
*/
|
*/
|
||||||
@ -138,3 +139,43 @@ encode_rmd160_value( byte *md, unsigned len, unsigned nbits )
|
|||||||
return frame;
|
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 "mpi.h"
|
||||||
#include "keydb.h"
|
#include "keydb.h"
|
||||||
#include "cipher.h"
|
#include "cipher.h"
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
|
||||||
/****************
|
/****************
|
||||||
@ -40,7 +41,7 @@ int
|
|||||||
signature_check( PKT_signature *sig, MD_HANDLE digest )
|
signature_check( PKT_signature *sig, MD_HANDLE digest )
|
||||||
{
|
{
|
||||||
PKT_pubkey_cert *pkc = m_alloc_clear( sizeof *pkc );
|
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;
|
int rc=0, i, j, c, old_enc;
|
||||||
byte *dp;
|
byte *dp;
|
||||||
|
|
||||||
@ -50,11 +51,168 @@ signature_check( PKT_signature *sig, MD_HANDLE digest )
|
|||||||
goto leave;
|
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;
|
RSA_public_key pkey;
|
||||||
|
|
||||||
|
result = mpi_alloc(40);
|
||||||
pkey.n = pkc->d.rsa.rsa_n;
|
pkey.n = pkc->d.rsa.rsa_n;
|
||||||
pkey.e = pkc->d.rsa.rsa_e;
|
pkey.e = pkc->d.rsa.rsa_e;
|
||||||
rsa_public( result, sig->d.rsa.rsa_integer, &pkey );
|
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 {
|
else {
|
||||||
log_debug("signature_check: unsupported pubkey algo %d\n",
|
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:
|
leave:
|
||||||
mpi_free( result );
|
|
||||||
if( pkc )
|
if( pkc )
|
||||||
free_pubkey_cert( pkc );
|
free_pubkey_cert( pkc );
|
||||||
|
mpi_free( result );
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,20 +38,27 @@
|
|||||||
#include "../cipher/elgamal.h"
|
#include "../cipher/elgamal.h"
|
||||||
|
|
||||||
|
|
||||||
#define CIPHER_ALGO_NONE 0
|
#define CIPHER_ALGO_NONE 0
|
||||||
#define CIPHER_ALGO_IDEA 1 /* used only for documentation */
|
#define CIPHER_ALGO_IDEA 1
|
||||||
#define CIPHER_ALGO_BLOWFISH 42
|
#define CIPHER_ALGO_3DES 2
|
||||||
#define CIPHER_ALGO_GOST 43
|
#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_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_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 {
|
typedef struct {
|
||||||
int algo;
|
int algo;
|
||||||
@ -78,12 +85,8 @@ byte get_random_byte( int level );
|
|||||||
extern ushort small_prime_numbers[];
|
extern ushort small_prime_numbers[];
|
||||||
|
|
||||||
/*-- primegen.c --*/
|
/*-- primegen.c --*/
|
||||||
MPI generate_random_prime( unsigned nbits );
|
MPI generate_secret_prime( unsigned nbits );
|
||||||
|
MPI generate_public_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 );
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*G10_CIPHER_H*/
|
#endif /*G10_CIPHER_H*/
|
||||||
|
@ -51,6 +51,7 @@ typedef struct mpi_struct {
|
|||||||
#define MPI_NULL NULL
|
#define MPI_NULL NULL
|
||||||
|
|
||||||
#define mpi_get_nlimbs(a) ((a)->nlimbs)
|
#define mpi_get_nlimbs(a) ((a)->nlimbs)
|
||||||
|
#define mpi_is_neg(a) ((a)->sign)
|
||||||
|
|
||||||
/*-- mpiutil.c --*/
|
/*-- mpiutil.c --*/
|
||||||
|
|
||||||
@ -101,13 +102,16 @@ u32 mpi_get_keyid( MPI a, u32 *keyid );
|
|||||||
/*-- mpi-add.c --*/
|
/*-- mpi-add.c --*/
|
||||||
void mpi_add_ui(MPI w, MPI u, ulong v );
|
void mpi_add_ui(MPI w, MPI u, ulong v );
|
||||||
void mpi_add(MPI w, MPI u, MPI 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_ui(MPI w, MPI u, ulong v );
|
||||||
void mpi_sub( MPI w, MPI u, MPI v);
|
void mpi_sub( MPI w, MPI u, MPI v);
|
||||||
|
void mpi_subm( MPI w, MPI u, MPI v, MPI m);
|
||||||
|
|
||||||
/*-- mpi-mul.c --*/
|
/*-- mpi-mul.c --*/
|
||||||
void mpi_mul_ui(MPI w, MPI u, ulong v );
|
void mpi_mul_ui(MPI w, MPI u, ulong v );
|
||||||
void mpi_mul_2exp( MPI w, MPI u, ulong cnt);
|
void mpi_mul_2exp( MPI w, MPI u, ulong cnt);
|
||||||
void mpi_mul( MPI w, MPI u, MPI v);
|
void mpi_mul( MPI w, MPI u, MPI v);
|
||||||
|
void mpi_mulm( MPI w, MPI u, MPI v, MPI m);
|
||||||
|
|
||||||
/*-- mpi-div.c --*/
|
/*-- mpi-div.c --*/
|
||||||
ulong mpi_fdiv_r_ui( MPI rem, MPI dividend, ulong divisor );
|
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 );
|
void mpi_rshift( MPI x, MPI a, unsigned n );
|
||||||
|
|
||||||
/*-- mpi-inv.c --*/
|
/*-- 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*/
|
#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
|
* 1 = (a*x) mod n
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
mpi_inv_mod( MPI x, MPI a, MPI n )
|
mpi_invm( MPI x, MPI a, MPI n )
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
MPI u, v, u1, u2, u3, v1, v2, v3, q, t1, t2, t3;
|
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);
|
fputs("stack underflow\n", stderr);
|
||||||
return;
|
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_set(stack[stackidx-2],a);
|
||||||
mpi_free(a);
|
mpi_free(a);
|
||||||
stackidx--;
|
stackidx--;
|
||||||
|
@ -110,9 +110,13 @@ log_bug( const char *fmt, ... )
|
|||||||
va_list arg_ptr ;
|
va_list arg_ptr ;
|
||||||
|
|
||||||
fprintf(stderr, "\nInternal Error%s: ", pidstring ) ;
|
fprintf(stderr, "\nInternal Error%s: ", pidstring ) ;
|
||||||
va_start( arg_ptr, fmt ) ;
|
if( fmt ) {
|
||||||
vfprintf(stderr,fmt,arg_ptr) ;
|
va_start( arg_ptr, fmt ) ;
|
||||||
va_end(arg_ptr);
|
vfprintf(stderr,fmt,arg_ptr) ;
|
||||||
|
va_end(arg_ptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fputs("Ohhh jeeee ...\n", stderr);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user