1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

fingerprints and self signatures added

This commit is contained in:
Werner Koch 1997-12-09 12:46:23 +00:00
parent 3b1b6f9d98
commit 935965049d
23 changed files with 783 additions and 444 deletions

8
TODO
View File

@ -4,15 +4,13 @@
this shoud espceially done for the buffer in the chain. this shoud espceially done for the buffer in the chain.
* add a way to difference between errors and eof in the underflow/flush * add a way to difference between errors and eof in the underflow/flush
function of iobuf. function of iobuf.
* filter all output read from the input when displaying it to the user. * check that all output is filtered when displayed.
* keyring editing * keyring editing
* add trust stuff * add trust stuff
* make ttyio.c work (hide passwords etc..) * make ttyio.c work (hide passwords etc..)
* add detached signatures
* add option file handling. * add option file handling.
* use correct ASN values for DEK encoding * use correct ASN values for DEK encoding
* add checking of armor trailers * add checking of armor trailers
* fix the memory stuff (secure memory)
* add real secure memory * add real secure memory
* look for a way to reuse RSA signatures * look for a way to reuse RSA signatures
* find a way to remove the armor filter after it * find a way to remove the armor filter after it
@ -24,10 +22,12 @@
* enable a SIGSEGV handler while using zlib functions * enable a SIGSEGV handler while using zlib functions
* PGP writes the signature and then the file, this is not * PGP writes the signature and then the file, this is not
a good idea, we can't write such files if we take input rom stdin. a good idea, we can't write such files if we take input from stdin.
So the solution will: accept such packet, but write So the solution will: accept such packet, but write
signature the corret way: first the data and then the signature[s] signature the corret way: first the data and then the signature[s]
this is much easier to check, also we must read the entire data this is much easier to check, also we must read the entire data
before we can check wether we have the pubkey or not. The one-pass before we can check wether we have the pubkey or not. The one-pass
signature packets should be implemented to avoid this. signature packets should be implemented to avoid this.
* compress does not work always!

View File

@ -95,7 +95,7 @@ gen_k( MPI p )
if( DBG_CIPHER ) if( DBG_CIPHER )
fputc('.', stderr); fputc('.', stderr);
mpi_set_bytes( k, nbits, get_random_byte, 1 ); mpi_set_bytes( k, nbits, get_random_byte, 1 );
mpi_set_bit( k, nbits-1 ); /* make sure it's high (needed?) */ mpi_set_bit( k, nbits-1 ); /* make sure it's high (really needed?) */
if( mpi_cmp( k, p_1 ) >= 0 ) if( mpi_cmp( k, p_1 ) >= 0 )
continue; /* is not smaller than (p-1) */ continue; /* is not smaller than (p-1) */
if( mpi_gcd( temp, k, p_1 ) ) if( mpi_gcd( temp, k, p_1 ) )
@ -136,7 +136,7 @@ elg_generate( ELG_public_key *pk, ELG_secret_key *sk, unsigned nbits )
fputc('.', stderr); fputc('.', stderr);
mpi_set_bytes( x, nbits, get_random_byte, 1 ); /* fixme: should be 2 */ 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?) */ mpi_set_bit( x, nbits-1 ); /* make sure it's high (needed?) */
} while( mpi_cmp( x, p ) >= 0 ); /* x must be samller than p */ } while( mpi_cmp( x, p ) >= 0 ); /* x must be smaller than p */
y = mpi_alloc(nbits/BITS_PER_MPI_LIMB); y = mpi_alloc(nbits/BITS_PER_MPI_LIMB);
mpi_powm( y, g, x, p ); mpi_powm( y, g, x, p );

View File

@ -98,7 +98,6 @@ gen_prime( unsigned nbits, int secret )
} }
if( x ) if( x )
continue; /* found a multiple of a already known prime */ continue; /* found a multiple of a already known prime */
if( DBG_CIPHER )
fputc('.', stderr); fputc('.', stderr);
mpi_add_ui( prime, prime, step ); mpi_add_ui( prime, prime, step );
@ -108,7 +107,6 @@ gen_prime( unsigned nbits, int secret )
mpi_powm( result, val_2, prime, prime ); mpi_powm( result, val_2, prime, prime );
if( mpi_cmp_ui(result, 2) ) if( mpi_cmp_ui(result, 2) )
continue; /* stepping (fermat test failed) */ continue; /* stepping (fermat test failed) */
if( DBG_CIPHER )
fputc('+', stderr); fputc('+', stderr);
/* perform stronger tests */ /* perform stronger tests */
@ -120,8 +118,9 @@ gen_prime( unsigned nbits, int secret )
break; /* step loop, cont with a new prime */ break; /* step loop, cont with a new prime */
} }
} }
if( DBG_CIPHER ) {
fputc('\n', stderr); fputc('\n', stderr);
if( DBG_CIPHER ) {
log_debug("performed %u simple and %u stronger tests\n", log_debug("performed %u simple and %u stronger tests\n",
count1, count2 ); count1, count2 );
log_mpidump("found prime: ", prime ); log_mpidump("found prime: ", prime );
@ -134,7 +133,6 @@ gen_prime( unsigned nbits, int secret )
return prime; return prime;
} }
} }
if( DBG_CIPHER )
fputc(':', stderr); /* restart with a new random value */ fputc(':', stderr); /* restart with a new random value */
} }
} }
@ -179,7 +177,6 @@ is_not_prime( MPI n, unsigned nbits, int steps, int *count )
if( j == k ) if( j == k )
goto leave; goto leave;
} }
if( DBG_CIPHER )
fputc('+', stderr); fputc('+', stderr);
} }
rc = 0; /* may be a prime */ rc = 0; /* may be a prime */

View File

@ -157,6 +157,22 @@ rsa_generate( RSA_public_key *pk, RSA_secret_key *sk, unsigned nbits )
} }
/****************
* Test wether the secret key is valid.
* Returns: true if this is a valid key.
*/
int
rsa_check_secret_key( RSA_secret_key *sk )
{
int rc;
MPI temp = mpi_alloc( mpi_get_nlimbs(sk->p)*2 );
mpi_mul(temp, sk->p, sk->q );
rc = mpi_cmp( temp, sk->n );
mpi_free(temp);
return !rc;
}
/**************** /****************

View File

@ -46,6 +46,7 @@ typedef struct {
void rsa_free_public_key( RSA_public_key *pk ); void rsa_free_public_key( RSA_public_key *pk );
void rsa_free_secret_key( RSA_secret_key *sk ); void rsa_free_secret_key( RSA_secret_key *sk );
void rsa_generate( RSA_public_key *pk, RSA_secret_key *sk, unsigned nbits ); void rsa_generate( RSA_public_key *pk, RSA_secret_key *sk, unsigned nbits );
int rsa_check_secret_key( RSA_secret_key *sk );
void rsa_public(MPI output, MPI input, RSA_public_key *skey ); void rsa_public(MPI output, MPI input, RSA_public_key *skey );
void rsa_secret(MPI output, MPI input, RSA_secret_key *skey ); void rsa_secret(MPI output, MPI input, RSA_secret_key *skey );

View File

@ -169,13 +169,13 @@ do_public_cert( IOBUF out, int ctb, PKT_public_cert *pkc )
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_ELGAMAL ) { if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
mpi_encode(a, pkc->d.elg.p ); mpi_write(a, pkc->d.elg.p );
mpi_encode(a, pkc->d.elg.g ); mpi_write(a, pkc->d.elg.g );
mpi_encode(a, pkc->d.elg.y ); mpi_write(a, pkc->d.elg.y );
} }
else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) { else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
mpi_encode(a, pkc->d.rsa.rsa_n ); mpi_write(a, pkc->d.rsa.rsa_n );
mpi_encode(a, pkc->d.rsa.rsa_e ); mpi_write(a, pkc->d.rsa.rsa_e );
} }
else { else {
rc = G10ERR_PUBKEY_ALGO; rc = G10ERR_PUBKEY_ALGO;
@ -191,6 +191,31 @@ do_public_cert( IOBUF out, int ctb, PKT_public_cert *pkc )
return rc; return rc;
} }
/****************
* Make a hash value from the public key certificate
*/
void
hash_public_cert( MD_HANDLE *md, PKT_public_cert *pkc )
{
PACKET pkt;
int rc = 0;
int c;
IOBUF a = iobuf_temp();
/* build the packet */
init_packet(&pkt);
pkt.pkttype = PKT_PUBLIC_CERT;
pkt.pkt.public_cert = pkc;
if( (rc = build_packet( a, &pkt )) )
log_fatal("build public_cert for hashing failed: %s\n", g10_errstr(rc));
while( (c=iobuf_get(a)) != -1 )
md_putchar( md, c );
iobuf_cancel(a);
}
static int static int
do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc ) do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc )
{ {
@ -202,48 +227,33 @@ do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc )
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_ELGAMAL ) { if( skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
mpi_encode(a, skc->d.elg.p ); mpi_write(a, skc->d.elg.p );
mpi_encode(a, skc->d.elg.g ); mpi_write(a, skc->d.elg.g );
mpi_encode(a, skc->d.elg.y ); mpi_write(a, skc->d.elg.y );
iobuf_put(a, skc->d.elg.protect_algo ); iobuf_put(a, skc->d.elg.protect_algo );
skc->d.elg.calc_csum = 0;
if( skc->d.elg.protect_algo ) { if( skc->d.elg.protect_algo ) {
assert( skc->d.elg.is_protected == 1 ); assert( skc->d.elg.is_protected == 1 );
assert( skc->d.elg.protect_algo == CIPHER_ALGO_BLOWFISH ); assert( skc->d.elg.protect_algo == CIPHER_ALGO_BLOWFISH );
iobuf_write(a, skc->d.elg.protect.blowfish.iv, 8 ); 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 ); mpi_write(a, skc->d.elg.x );
write_16(a, skc->d.elg.csum );
} }
else if( skc->pubkey_algo == PUBKEY_ALGO_RSA ) { else if( skc->pubkey_algo == PUBKEY_ALGO_RSA ) {
mpi_encode(a, skc->d.rsa.rsa_n ); mpi_write(a, skc->d.rsa.rsa_n );
mpi_encode(a, skc->d.rsa.rsa_e ); mpi_write(a, skc->d.rsa.rsa_e );
iobuf_put(a, skc->d.rsa.protect_algo ); iobuf_put(a, skc->d.rsa.protect_algo );
skc->d.rsa.calc_csum = 0;
if( skc->d.rsa.protect_algo ) { if( skc->d.rsa.protect_algo ) {
assert( skc->d.rsa.is_protected == 1 ); assert( skc->d.rsa.is_protected == 1 );
assert( skc->d.rsa.protect_algo == CIPHER_ALGO_BLOWFISH ); assert( skc->d.rsa.protect_algo == CIPHER_ALGO_BLOWFISH );
iobuf_write(a, skc->d.rsa.protect.blowfish.iv, 8 ); iobuf_write(a, skc->d.rsa.protect.blowfish.iv, 8 );
mpi_write_csum(a, (byte*)skc->d.rsa.rsa_d, &skc->d.rsa.calc_csum );
mpi_write_csum(a, (byte*)skc->d.rsa.rsa_p, &skc->d.rsa.calc_csum );
mpi_write_csum(a, (byte*)skc->d.rsa.rsa_q, &skc->d.rsa.calc_csum );
mpi_write_csum(a, (byte*)skc->d.rsa.rsa_u, &skc->d.rsa.calc_csum );
} }
else { /* Not protected: You fool you! */ mpi_write(a, skc->d.rsa.rsa_d );
assert( !skc->d.rsa.is_protected ); mpi_write(a, skc->d.rsa.rsa_p );
mpi_encode_csum(a, skc->d.rsa.rsa_d, &skc->d.rsa.calc_csum ); mpi_write(a, skc->d.rsa.rsa_q );
mpi_encode_csum(a, skc->d.rsa.rsa_p, &skc->d.rsa.calc_csum ); mpi_write(a, skc->d.rsa.rsa_u );
mpi_encode_csum(a, skc->d.rsa.rsa_q, &skc->d.rsa.calc_csum ); write_16(a, skc->d.rsa.csum );
mpi_encode_csum(a, skc->d.rsa.rsa_u, &skc->d.rsa.calc_csum );
}
write_16(a, skc->d.rsa.calc_csum );
} }
else { else {
rc = G10ERR_PUBKEY_ALGO; rc = G10ERR_PUBKEY_ALGO;
@ -270,11 +280,11 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
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_ELGAMAL ) { if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
mpi_encode(a, enc->d.elg.a ); mpi_write(a, enc->d.elg.a );
mpi_encode(a, enc->d.elg.b ); mpi_write(a, enc->d.elg.b );
} }
else if( enc->pubkey_algo == PUBKEY_ALGO_RSA ) { else if( enc->pubkey_algo == PUBKEY_ALGO_RSA ) {
mpi_encode(a, enc->d.rsa.rsa_integer ); mpi_write(a, enc->d.rsa.rsa_integer );
} }
else { else {
rc = G10ERR_PUBKEY_ALGO; rc = G10ERR_PUBKEY_ALGO;
@ -379,14 +389,14 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig )
iobuf_put(a, sig->d.elg.digest_algo ); 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[0] );
iobuf_put(a, sig->d.elg.digest_start[1] ); iobuf_put(a, sig->d.elg.digest_start[1] );
mpi_encode(a, sig->d.elg.a ); mpi_write(a, sig->d.elg.a );
mpi_encode(a, sig->d.elg.b ); mpi_write(a, sig->d.elg.b );
} }
else if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) { 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] );
mpi_encode(a, sig->d.rsa.rsa_integer ); mpi_write(a, sig->d.rsa.rsa_integer );
} }
else { else {
rc = G10ERR_PUBKEY_ALGO; rc = G10ERR_PUBKEY_ALGO;

View File

@ -100,27 +100,16 @@ free_secret_cert( PKT_secret_cert *cert )
mpi_free( cert->d.elg.p ); mpi_free( cert->d.elg.p );
mpi_free( cert->d.elg.g ); mpi_free( cert->d.elg.g );
mpi_free( cert->d.elg.y ); mpi_free( cert->d.elg.y );
if( cert->d.rsa.is_protected )
m_free( cert->d.elg.x );
else
mpi_free( cert->d.elg.x ); mpi_free( cert->d.elg.x );
} }
else if( cert->pubkey_algo == PUBKEY_ALGO_RSA ) { else if( cert->pubkey_algo == PUBKEY_ALGO_RSA ) {
mpi_free( cert->d.rsa.rsa_n ); mpi_free( cert->d.rsa.rsa_n );
mpi_free( cert->d.rsa.rsa_e ); mpi_free( cert->d.rsa.rsa_e );
if( cert->d.rsa.is_protected ) {
m_free( cert->d.rsa.rsa_d );
m_free( cert->d.rsa.rsa_p );
m_free( cert->d.rsa.rsa_q );
m_free( cert->d.rsa.rsa_u );
}
else {
mpi_free( cert->d.rsa.rsa_d ); mpi_free( cert->d.rsa.rsa_d );
mpi_free( cert->d.rsa.rsa_p ); mpi_free( cert->d.rsa.rsa_p );
mpi_free( cert->d.rsa.rsa_q ); mpi_free( cert->d.rsa.rsa_q );
mpi_free( cert->d.rsa.rsa_u ); mpi_free( cert->d.rsa.rsa_u );
} }
}
m_free(cert); m_free(cert);
} }

View File

@ -124,6 +124,8 @@ main( int argc, char **argv )
{ 512, "cache-all" ,0, "hold everything in memory"}, { 512, "cache-all" ,0, "hold everything in memory"},
{ 513, "gen-prime" , 1, "\rgenerate a prime of length n" }, { 513, "gen-prime" , 1, "\rgenerate a prime of length n" },
{ 514, "test" , 0, "\rdevelopment usage" }, { 514, "test" , 0, "\rdevelopment usage" },
{ 515, "change-passphrase", 0, "change the passphrase of your secret keyring"},
{ 515, "fingerprint", 0, "show the fingerprints"},
{0} }; {0} };
ARGPARSE_ARGS pargs = { &argc, &argv, 0 }; ARGPARSE_ARGS pargs = { &argc, &argv, 0 };
IOBUF a; IOBUF a;
@ -136,11 +138,14 @@ main( int argc, char **argv )
int nrings=0; int nrings=0;
armor_filter_context_t afx; armor_filter_context_t afx;
const char *s; const char *s;
int detached_sig = 0;
opt.compress = -1; /* defaults to default compression level */ opt.compress = -1; /* defaults to default compression level */
while( arg_parse( &pargs, opts) ) { while( arg_parse( &pargs, opts) ) {
switch( pargs.r_opt ) { switch( pargs.r_opt ) {
case 'v': opt.verbose++; break; case 'v': opt.verbose++;
opt.list_sigs=1;
break;
case 'z': case 'z':
opt.compress = pargs.r.ret_int; opt.compress = pargs.r.ret_int;
break; break;
@ -151,7 +156,7 @@ main( int argc, char **argv )
opt.outfile_is_stdout = 1; opt.outfile_is_stdout = 1;
break; break;
case 'e': action = action == aSign? aSignEncr : aEncr; break; case 'e': action = action == aSign? aSignEncr : aEncr; break;
case 'b': opt.detached_sig = 1; case 'b': detached_sig = 1;
/* fall trough */ /* fall trough */
case 's': action = action == aEncr? aSignEncr : aSign; break; case 's': action = action == aEncr? aSignEncr : aSign; break;
case 'l': /* store the local users */ case 'l': /* store the local users */
@ -171,13 +176,14 @@ main( int argc, char **argv )
case 502: opt.answer_no = 1; break; case 502: opt.answer_no = 1; break;
case 503: action = aKeygen; break; case 503: action = aKeygen; break;
case 507: action = aStore; break; case 507: action = aStore; break;
case 508: opt.check_sigs = 1; break; case 508: opt.check_sigs = 1; opt.list_sigs = 1; break;
case 509: add_keyring(pargs.r.ret_str); nrings++; break; case 509: add_keyring(pargs.r.ret_str); nrings++; break;
case 510: opt.debug |= pargs.r.ret_ulong; break; case 510: opt.debug |= pargs.r.ret_ulong; break;
case 511: opt.debug = ~0; break; case 511: opt.debug = ~0; break;
case 512: opt.cache_all = 1; break; case 512: opt.cache_all = 1; break;
case 513: action = aPrimegen; break; case 513: action = aPrimegen; break;
case 514: action = aTest; break; case 514: action = aTest; break;
case 515: opt.fingerprint = 1; break;
default : pargs.err = 2; break; default : pargs.err = 2; break;
} }
} }
@ -230,7 +236,7 @@ main( int argc, char **argv )
case aSign: /* sign the given file */ case aSign: /* sign the given file */
if( argc > 1 ) if( argc > 1 )
usage(1); usage(1);
if( (rc = sign_file(fname, opt.detached_sig, locusr)) ) if( (rc = sign_file(fname, detached_sig, locusr)) )
log_error("sign_file('%s'): %s\n", fname_print, g10_errstr(rc) ); log_error("sign_file('%s'): %s\n", fname_print, g10_errstr(rc) );
break; break;

View File

@ -50,6 +50,8 @@ unsigned nbits_from_skc( PKT_secret_cert *skc );
const char *datestr_from_pkc( PKT_public_cert *pkc ); const char *datestr_from_pkc( PKT_public_cert *pkc );
const char *datestr_from_skc( PKT_secret_cert *skc ); const char *datestr_from_skc( PKT_secret_cert *skc );
const char *datestr_from_sig( PKT_signature *sig ); const char *datestr_from_sig( PKT_signature *sig );
byte *fingerprint_from_skc( PKT_secret_cert *skc, size_t *ret_len );
byte *fingerprint_from_pkc( PKT_public_cert *pkc, size_t *ret_len );

View File

@ -51,9 +51,44 @@ answer_is_yes( const char *s )
} }
static u16
checksum_u16( unsigned n )
{
u16 a;
a = (n >> 8) & 0xff;
a |= n & 0xff;
return a;
}
static u16
checksum( byte *p, unsigned n )
{
u16 a;
for(a=0; n; n-- )
a += *p++;
return a;
}
static u16
checksum_mpi( MPI a )
{
u16 csum;
byte *buffer;
unsigned nbytes;
buffer = mpi_get_buffer( a, &nbytes, NULL );
csum = checksum_u16( nbytes*8 );
csum += checksum( buffer, nbytes );
m_free( buffer );
return csum;
}
static void static void
write_uid( IOBUF out, const char *s ) write_uid( IOBUF out, const char *s, PKT_user_id **upkt )
{ {
PACKET pkt; PACKET pkt;
size_t n = strlen(s); size_t n = strlen(s);
@ -65,13 +100,44 @@ write_uid( IOBUF out, const char *s )
strcpy(pkt.pkt.user_id->name, s); strcpy(pkt.pkt.user_id->name, s);
if( (rc = build_packet( out, &pkt )) ) if( (rc = build_packet( out, &pkt )) )
log_error("build_packet(user_id) failed: %s\n", g10_errstr(rc) ); log_error("build_packet(user_id) failed: %s\n", g10_errstr(rc) );
if( upkt ) {
*upkt = pkt.pkt.user_id;
pkt.pkt.user_id = NULL;
}
free_packet( &pkt ); free_packet( &pkt );
} }
static int
write_selfsig( IOBUF out, PKT_public_cert *pkc, PKT_user_id *uid,
PKT_secret_cert *skc )
{
PACKET pkt;
PKT_signature *sig;
int rc=0;
if( opt.verbose )
log_info("writing self signature\n");
rc = make_keysig_packet( &sig, pkc, uid, skc, 0x13, DIGEST_ALGO_RMD160 );
if( rc ) {
log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) );
return rc;
}
pkt.pkttype = PKT_SIGNATURE;
pkt.pkt.signature = sig;
if( (rc = build_packet( out, &pkt )) )
log_error("build_packet(signature) failed: %s\n", g10_errstr(rc) );
free_packet( &pkt );
return rc;
}
#ifdef HAVE_RSA_CIPHER #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, DEK *dek,
PKT_public_cert **ret_pkc, PKT_secret_cert **ret_skc )
{ {
int rc; int rc;
PACKET pkt1, pkt2; PACKET pkt1, pkt2;
@ -80,6 +146,9 @@ gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
RSA_public_key pk; RSA_public_key pk;
RSA_secret_key sk; RSA_secret_key sk;
init_packet(&pkt1);
init_packet(&pkt2);
rsa_generate( &pk, &sk, nbits ); rsa_generate( &pk, &sk, nbits );
skc = m_alloc( sizeof *skc ); skc = m_alloc( sizeof *skc );
@ -96,15 +165,28 @@ gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
skc->d.rsa.rsa_p = sk.p; skc->d.rsa.rsa_p = sk.p;
skc->d.rsa.rsa_q = sk.q; skc->d.rsa.rsa_q = sk.q;
skc->d.rsa.rsa_u = sk.u; skc->d.rsa.rsa_u = sk.u;
skc->d.rsa.calc_csum = 0; skc->d.rsa.csum = checksum_mpi( skc->d.rsa.rsa_d );
skc->d.rsa.is_protected = 0; /* FIXME!!! */ skc->d.rsa.csum += checksum_mpi( skc->d.rsa.rsa_p );
skc->d.rsa.protect_algo = 0; /* should be blowfish */ skc->d.rsa.csum += checksum_mpi( skc->d.rsa.rsa_q );
/*memcpy(skc->d.rsa.protect.blowfish.iv,"12345678", 8);*/ skc->d.rsa.csum += checksum_mpi( skc->d.rsa.rsa_u );
if( !dek ) {
skc->d.rsa.is_protected = 0;
skc->d.rsa.protect_algo = 0;
}
else {
skc->d.rsa.is_protected = 1;
skc->d.rsa.protect_algo = CIPHER_ALGO_BLOWFISH;
randomize_buffer( skc->d.rsa.protect.blowfish.iv, 8, 1);
skc->d.rsa.csum += checksum( skc->d.rsa.protect.blowfish.iv, 8 );
rc = protect_secret_key( skc, dek );
if( rc ) {
log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
goto leave;
}
}
init_packet(&pkt1);
pkt1.pkttype = PKT_PUBLIC_CERT; pkt1.pkttype = PKT_PUBLIC_CERT;
pkt1.pkt.public_cert = pkc; pkt1.pkt.public_cert = pkc;
init_packet(&pkt2);
pkt2.pkttype = PKT_SECRET_CERT; pkt2.pkttype = PKT_SECRET_CERT;
pkt2.pkt.secret_cert = skc; pkt2.pkt.secret_cert = skc;
@ -116,6 +198,10 @@ gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
log_error("build secret_cert packet failed: %s\n", g10_errstr(rc) ); log_error("build secret_cert packet failed: %s\n", g10_errstr(rc) );
goto leave; goto leave;
} }
*ret_pkc = pkt1.pkt.public_cert;
pkt1.pkt.public_cert = NULL;
*ret_skc = pkt1.pkt.secret_cert;
pkt1.pkt.secret_cert = NULL;
leave: leave:
free_packet(&pkt1); free_packet(&pkt1);
@ -125,14 +211,19 @@ gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
#endif /*HAVE_RSA_CIPHER*/ #endif /*HAVE_RSA_CIPHER*/
static int static int
gen_elg(unsigned nbits, IOBUF pub_io, IOBUF sec_io) gen_elg(unsigned nbits, IOBUF pub_io, IOBUF sec_io, DEK *dek,
PKT_public_cert **ret_pkc, PKT_secret_cert **ret_skc )
{ {
int rc; int rc;
PACKET pkt1, pkt2; PACKET pkt1, pkt2;
PKT_secret_cert *skc; PKT_secret_cert *skc, *unprotected_skc;
PKT_public_cert *pkc; PKT_public_cert *pkc;
ELG_public_key pk; ELG_public_key pk;
ELG_secret_key sk; ELG_secret_key sk;
unsigned nbytes;
init_packet(&pkt1);
init_packet(&pkt2);
elg_generate( &pk, &sk, nbits ); elg_generate( &pk, &sk, nbits );
@ -150,15 +241,25 @@ gen_elg(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
skc->d.elg.y = sk.y; skc->d.elg.y = sk.y;
skc->d.elg.x = sk.x; skc->d.elg.x = sk.x;
skc->d.elg.calc_csum = 0; skc->d.elg.csum = checksum_mpi( skc->d.elg.x );
skc->d.elg.is_protected = 0; /* FIXME!!! */ unprotected_skc = copy_secret_cert( NULL, skc );
skc->d.elg.protect_algo = 0; /* should be blowfish */ if( !dek ) {
/*memcpy(skc->d.elg.protect.blowfish.iv,"12345678", 8);*/ skc->d.elg.is_protected = 0;
skc->d.elg.protect_algo = 0;
}
else {
skc->d.elg.is_protected = 0;
skc->d.elg.protect_algo = CIPHER_ALGO_BLOWFISH;
randomize_buffer(skc->d.elg.protect.blowfish.iv, 8, 1);
rc = protect_secret_key( skc, dek );
if( rc ) {
log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
goto leave;
}
}
init_packet(&pkt1);
pkt1.pkttype = PKT_PUBLIC_CERT; pkt1.pkttype = PKT_PUBLIC_CERT;
pkt1.pkt.public_cert = pkc; pkt1.pkt.public_cert = pkc;
init_packet(&pkt2);
pkt2.pkttype = PKT_SECRET_CERT; pkt2.pkttype = PKT_SECRET_CERT;
pkt2.pkt.secret_cert = skc; pkt2.pkt.secret_cert = skc;
@ -170,10 +271,17 @@ gen_elg(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
log_error("build secret_cert packet failed: %s\n", g10_errstr(rc) ); log_error("build secret_cert packet failed: %s\n", g10_errstr(rc) );
goto leave; goto leave;
} }
*ret_pkc = pkt1.pkt.public_cert;
pkt1.pkt.public_cert = NULL;
*ret_skc = unprotected_skc;
unprotected_skc = NULL;
leave: leave:
free_packet(&pkt1); free_packet(&pkt1);
free_packet(&pkt2); free_packet(&pkt2);
if( unprotected_skc )
free_secret_cert( unprotected_skc );
return rc; return rc;
} }
@ -192,6 +300,10 @@ generate_keypair()
char *uid = NULL; char *uid = NULL;
IOBUF pub_io = NULL; IOBUF pub_io = NULL;
IOBUF sec_io = NULL; IOBUF sec_io = NULL;
PKT_public_cert *pkc = NULL;
PKT_secret_cert *skc = NULL;
PKT_user_id *upkt = NULL;
DEK *dek = NULL;
int rc; int rc;
int algo; int algo;
const char *algo_name; const char *algo_name;
@ -301,6 +413,28 @@ generate_keypair()
} }
} }
#endif #endif
tty_printf( "You need a Passphrase to protect your secret key.\n\n" );
dek = m_alloc_secure( sizeof *dek );
dek->algo = CIPHER_ALGO_BLOWFISH;
rc = make_dek_from_passphrase( dek , 2 );
if( rc == -1 ) {
m_free(dek); dek = NULL;
tty_printf(
"You don't what a passphrase - this is probably a *bad* idea!\n"
"I will do it anyway. You can change your passphrase at anytime,\n"
"using this program with the option \"--change-passphrase\"\n\n" );
}
else if( rc ) {
m_free(dek); dek = NULL;
m_free(uid);
log_error("Error getting the passphrase: %s\n", g10_errstr(rc) );
return;
}
/* 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 )) )
@ -334,23 +468,41 @@ generate_keypair()
return; return;
} }
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 );
if( algo == PUBKEY_ALGO_ELGAMAL ) if( algo == PUBKEY_ALGO_ELGAMAL )
gen_elg(nbits, pub_io, sec_io); rc = gen_elg(nbits, pub_io, sec_io, dek, &pkc, &skc);
#ifdef HAVE_RSA_CIPHER #ifdef HAVE_RSA_CIPHER
else if( algo == PUBKEY_ALGO_RSA ) else if( algo == PUBKEY_ALGO_RSA )
gen_rsa(nbits, pub_io, sec_io); rc = gen_rsa(nbits, pub_io, sec_io, dek, &pkc, &skc);
#endif #endif
else else
log_bug(NULL); log_bug(NULL);
write_uid(pub_io, uid ); if( !rc )
write_uid(sec_io, uid ); write_uid(pub_io, uid, &upkt );
m_free(uid); if( !rc )
write_uid(sec_io, uid, NULL );
if( !rc )
rc = write_selfsig(pub_io, pkc, upkt, skc );
if( rc ) {
iobuf_cancel(pub_io);
iobuf_cancel(sec_io);
tty_printf("Key generation failed: %s\n", g10_errstr(rc) );
}
else {
iobuf_close(pub_io); iobuf_close(pub_io);
iobuf_close(sec_io); iobuf_close(sec_io);
tty_printf("public and secret key created and signed.\n" );
}
if( pkc )
free_public_cert( pkc );
if( skc )
free_secret_cert( skc );
if( upkt )
free_user_id( upkt );
m_free(uid);
m_free(dek);
} }

View File

@ -171,3 +171,110 @@ datestr_from_sig( PKT_signature *sig )
return buffer; return buffer;
} }
/**************** .
* Return a byte array with the fingerprint for the given PKC/SKC
* The length of the array is returned in ret_len. Caller must free
* the array.
*/
byte *
fingerprint_from_skc( PKT_secret_cert *skc, size_t *ret_len )
{
PKT_public_cert pkc;
byte *p;
pkc.pubkey_algo = skc->pubkey_algo;
if( pkc.pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
pkc.timestamp = skc->timestamp;
pkc.valid_days = skc->valid_days;
pkc.pubkey_algo = skc->pubkey_algo;
pkc.d.elg.p = skc->d.elg.p;
pkc.d.elg.g = skc->d.elg.g;
pkc.d.elg.y = skc->d.elg.y;
}
else if( pkc.pubkey_algo == PUBKEY_ALGO_RSA ) {
pkc.d.rsa.rsa_n = skc->d.rsa.rsa_n;
pkc.d.rsa.rsa_e = skc->d.rsa.rsa_e;
}
p = fingerprint_from_pkc( &pkc, ret_len );
memset(&pkc, 0, sizeof pkc); /* not really needed */
return p;
}
byte *
fingerprint_from_pkc( PKT_public_cert *pkc, size_t *ret_len )
{
byte *p, *buf, *array;
size_t len;
unsigned n;
if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
RMDHANDLE md;
const char *dp;
md = rmd160_open(0);
{ u32 a = pkc->timestamp;
rmd160_putchar( md, a >> 24 );
rmd160_putchar( md, a >> 16 );
rmd160_putchar( md, a >> 8 );
rmd160_putchar( md, a );
}
{ u16 a = pkc->valid_days;
rmd160_putchar( md, a >> 8 );
rmd160_putchar( md, a );
}
rmd160_putchar( md, pkc->pubkey_algo );
p = buf = mpi_get_buffer( pkc->d.elg.p, &n, NULL );
for( ; !*p && n; p++, n-- )
;
rmd160_putchar( md, n>>8); rmd160_putchar( md, n ); rmd160_write( md, p, n );
m_free(buf);
p = buf = mpi_get_buffer( pkc->d.elg.g, &n, NULL );
for( ; !*p && n; p++, n-- )
;
rmd160_putchar( md, n>>8); rmd160_putchar( md, n ); rmd160_write( md, p, n );
m_free(buf);
p = buf = mpi_get_buffer( pkc->d.elg.y, &n, NULL );
for( ; !*p && n; p++, n-- )
;
rmd160_putchar( md, n>>8); rmd160_putchar( md, n ); rmd160_write( md, p, n );
m_free(buf);
dp = rmd160_final(md);
array = m_alloc( 20 );
len = 20;
memcpy(array, dp, 20 );
rmd160_close(md);
}
else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
MD5HANDLE md;
md = md5_open(0);
p = buf = mpi_get_buffer( pkc->d.rsa.rsa_n, &n, NULL );
for( ; !*p && n; p++, n-- )
;
md5_write( md, p, n );
m_free(buf);
p = buf = mpi_get_buffer( pkc->d.rsa.rsa_e, &n, NULL );
for( ; !*p && n; p++, n-- )
;
md5_write( md, p, n );
m_free(buf);
md5_final(md);
array = m_alloc( 16 );
len = 16;
memcpy(array, md5_read(md), 16 );
md5_close(md);
}
else {
array = m_alloc(1);
len = 0; /* ooops */
}
*ret_len = len;
return array;
}

View File

@ -342,7 +342,7 @@ proc_plaintext( CTX c, PACKET *pkt )
printf("txt: plain text data name='%.*s'\n", pt->namelen, pt->name); printf("txt: plain text data name='%.*s'\n", pt->namelen, pt->name);
free_md_filter_context( &c->mfx ); free_md_filter_context( &c->mfx );
/* fixme: take the digest algo to use from the /* fixme: take the digest algo to use from the
* onpass_sig packet (if we have these) */ * onepass_sig packet (if we have these) */
c->mfx.md = md_open(DIGEST_ALGO_RMD160, 0); c->mfx.md = md_open(DIGEST_ALGO_RMD160, 0);
result = handle_plaintext( pt, &c->mfx ); result = handle_plaintext( pt, &c->mfx );
if( !result ) if( !result )
@ -450,6 +450,34 @@ print_userid( PACKET *pkt )
} }
static void
print_fingerprint( PKT_public_cert *pkc, PKT_secret_cert *skc )
{
byte *array, *p;
size_t i, n;
p = array = skc? fingerprint_from_skc( skc, &n )
: fingerprint_from_pkc( pkc, &n );
printf(" Key fingerprint =");
if( n == 20 ) {
for(i=0; i < n ; i++, i++, p += 2 ) {
if( i == 10 )
putchar(' ');
printf(" %02X%02X", *p, p[1] );
}
}
else {
for(i=0; i < n ; i++, p++ ) {
if( i && !(i%8) )
putchar(' ');
printf(" %02X", *p );
}
}
putchar('\n');
m_free(array);
}
/**************** /****************
* List the certificate in a user friendly way * List the certificate in a user friendly way
*/ */
@ -478,6 +506,8 @@ list_node( CTX c, NODE node )
printf( "%*s", 31, "" ); printf( "%*s", 31, "" );
print_userid( n2->pkt ); print_userid( n2->pkt );
putchar('\n'); putchar('\n');
if( opt.fingerprint && n2 == node->child )
print_fingerprint( pkc, NULL );
list_node(c, n2 ); list_node(c, n2 );
} }
} }
@ -491,11 +521,13 @@ list_node( CTX c, NODE node )
datestr_from_skc( skc ) ); datestr_from_skc( skc ) );
n2 = node->child; n2 = node->child;
if( !n2 ) if( !n2 )
printf("ERROR: no user id!"); printf("ERROR: no user id!\n");
else { else {
print_userid( n2->pkt ); print_userid( n2->pkt );
}
putchar('\n'); putchar('\n');
if( opt.fingerprint && n2 == node->child )
print_fingerprint( NULL, skc );
}
} }
else if( node->pkt->pkttype == PKT_USER_ID ) { else if( node->pkt->pkttype == PKT_USER_ID ) {
/* list everything under this user id */ /* list everything under this user id */
@ -510,6 +542,9 @@ list_node( CTX c, NODE node )
int sigrc = ' '; int sigrc = ' ';
assert( !node->child ); assert( !node->child );
if( !opt.list_sigs )
return;
if( opt.check_sigs ) { if( opt.check_sigs ) {
switch( (rc2=do_check_sig( c, node )) ) { switch( (rc2=do_check_sig( c, node )) ) {

View File

@ -32,8 +32,8 @@ struct {
int answer_no; /* answer no on most questions */ int answer_no; /* answer no on most questions */
int check_sigs; /* check key signatures */ int check_sigs; /* check key signatures */
int cache_all; int cache_all;
int detached_sig; int fingerprint; /* list fingerprints */
int reserved3; int list_sigs; /* list signatures */
int reserved4; int reserved4;
int reserved5; int reserved5;
int reserved6; int reserved6;

View File

@ -124,7 +124,6 @@ typedef struct {
MPI rsa_q; /* secret second prime number */ MPI rsa_q; /* secret second prime number */
MPI rsa_u; /* secret multiplicative inverse */ MPI rsa_u; /* secret multiplicative inverse */
u16 csum; /* checksum */ u16 csum; /* checksum */
u16 calc_csum; /* and a place to store the calculated csum */
byte is_protected; /* The above infos are protected and must */ byte is_protected; /* The above infos are protected and must */
/* be decrypteded before use */ /* be decrypteded before use */
byte protect_algo; /* cipher used to protect the secret informations*/ byte protect_algo; /* cipher used to protect the secret informations*/
@ -142,7 +141,6 @@ typedef struct {
MPI y; /* g^x mod p */ MPI y; /* g^x mod p */
MPI x; /* secret exponent */ MPI x; /* secret exponent */
u16 csum; /* checksum */ u16 csum; /* checksum */
u16 calc_csum; /* and a place to store the calculated csum */
byte is_protected; /* The above infos are protected and must */ byte is_protected; /* The above infos are protected and must */
/* be decrypteded before use */ /* be decrypteded before use */
byte protect_algo; /* cipher used to protect the secret informations*/ byte protect_algo; /* cipher used to protect the secret informations*/
@ -220,6 +218,7 @@ int parse_packet( IOBUF inp, PACKET *ret_pkt);
/*-- build-packet.c --*/ /*-- build-packet.c --*/
int build_packet( IOBUF inp, PACKET *pkt ); int build_packet( IOBUF inp, PACKET *pkt );
u32 calc_packet_length( PACKET *pkt ); u32 calc_packet_length( PACKET *pkt );
void hash_public_cert( MD_HANDLE *md, PKT_public_cert *pkc );
/*-- free-packet.c --*/ /*-- free-packet.c --*/
void free_pubkey_enc( PKT_pubkey_enc *enc ); void free_pubkey_enc( PKT_pubkey_enc *enc );
@ -238,6 +237,7 @@ int signature_check( PKT_signature *sig, MD_HANDLE *digest );
/*-- seckey-cert.c --*/ /*-- seckey-cert.c --*/
int check_secret_key( PKT_secret_cert *cert ); int check_secret_key( PKT_secret_cert *cert );
int protect_secret_key( PKT_secret_cert *cert, DEK *dek );
/*-- pubkey-enc.c --*/ /*-- pubkey-enc.c --*/
int get_session_key( PKT_pubkey_enc *k, DEK *dek ); int get_session_key( PKT_pubkey_enc *k, DEK *dek );
@ -256,5 +256,9 @@ int ask_for_detached_datafile( md_filter_context_t *mfx );
/*-- comment.c --*/ /*-- comment.c --*/
int write_comment( IOBUF out, const char *s ); int write_comment( IOBUF out, const char *s );
/*-- sign.c --*/
int make_keysig_packet( PKT_signature **ret_sig, PKT_public_cert *pkc,
PKT_user_id *uid, PKT_secret_cert *skc,
int sigclass, int digest_algo );
#endif /*G10_PACKET_H*/ #endif /*G10_PACKET_H*/

View File

@ -239,8 +239,8 @@ parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
k->keyid[0], k->keyid[1]); k->keyid[0], k->keyid[1]);
if( k->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { if( k->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
n = pktlen; n = pktlen;
k->d.elg.a = mpi_decode(inp, &n ); pktlen -=n; k->d.elg.a = mpi_read(inp, &n, 0); pktlen -=n;
k->d.elg.b = mpi_decode(inp, &n ); pktlen -=n; k->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) { if( list_mode ) {
printf("\telg a: "); printf("\telg a: ");
mpi_print(stdout, k->d.elg.a, mpi_print_mode ); mpi_print(stdout, k->d.elg.a, mpi_print_mode );
@ -251,7 +251,7 @@ parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
} }
else if( k->pubkey_algo == PUBKEY_ALGO_RSA ) { 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_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) { if( list_mode ) {
printf("\trsa integer: "); printf("\trsa integer: ");
mpi_print(stdout, k->d.rsa.rsa_integer, mpi_print_mode ); mpi_print(stdout, k->d.rsa.rsa_integer, mpi_print_mode );
@ -304,8 +304,8 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
sig->d.elg.digest_start[0] = 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--; sig->d.elg.digest_start[1] = iobuf_get_noeof(inp); pktlen--;
n = pktlen; n = pktlen;
sig->d.elg.a = mpi_decode(inp, &n ); pktlen -=n; sig->d.elg.a = mpi_read(inp, &n, 0 ); pktlen -=n;
sig->d.elg.b = mpi_decode(inp, &n ); pktlen -=n; sig->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) { if( list_mode ) {
printf("\tdigest algo %d, begin of digest %02x %02x\n", printf("\tdigest algo %d, begin of digest %02x %02x\n",
sig->d.elg.digest_algo, sig->d.elg.digest_algo,
@ -313,7 +313,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
printf("\telg a: "); printf("\telg a: ");
mpi_print(stdout, sig->d.elg.a, mpi_print_mode ); mpi_print(stdout, sig->d.elg.a, mpi_print_mode );
printf("\n\telg b: "); printf("\n\telg b: ");
mpi_print(stdout, sig->d.elg.a, mpi_print_mode ); mpi_print(stdout, sig->d.elg.b, mpi_print_mode );
putchar('\n'); putchar('\n');
} }
} }
@ -326,7 +326,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
sig->d.rsa.digest_start[0] = iobuf_get_noeof(inp); pktlen--; sig->d.rsa.digest_start[0] = iobuf_get_noeof(inp); pktlen--;
sig->d.rsa.digest_start[1] = iobuf_get_noeof(inp); pktlen--; sig->d.rsa.digest_start[1] = iobuf_get_noeof(inp); pktlen--;
n = pktlen; n = pktlen;
sig->d.rsa.rsa_integer = mpi_decode(inp, &n ); pktlen -=n; sig->d.rsa.rsa_integer = mpi_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) { if( list_mode ) {
printf("\tdigest algo %d, begin of digest %02x %02x\n", printf("\tdigest algo %d, begin of digest %02x %02x\n",
sig->d.rsa.digest_algo, sig->d.rsa.digest_algo,
@ -439,9 +439,9 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
if( algorithm == PUBKEY_ALGO_ELGAMAL ) { if( algorithm == PUBKEY_ALGO_ELGAMAL ) {
MPI elg_p, elg_g, elg_y; MPI elg_p, elg_g, elg_y;
n = pktlen; elg_p = mpi_decode(inp, &n ); pktlen -=n; n = pktlen; elg_p = mpi_read(inp, &n, 0 ); pktlen -=n;
n = pktlen; elg_g = mpi_decode(inp, &n ); pktlen -=n; n = pktlen; elg_g = mpi_read(inp, &n, 0 ); pktlen -=n;
n = pktlen; elg_y = mpi_decode(inp, &n ); pktlen -=n; n = pktlen; elg_y = mpi_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) { if( list_mode ) {
printf( "\telg p: "); printf( "\telg p: ");
mpi_print(stdout, elg_p, mpi_print_mode ); mpi_print(stdout, elg_p, mpi_print_mode );
@ -483,32 +483,24 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
else else
cert->d.elg.is_protected = 0; cert->d.elg.is_protected = 0;
n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2); n = pktlen; cert->d.elg.x = mpi_read(inp, &n, 1 ); pktlen -=n;
cert->d.elg.x = (MPI)mpibuf;
cert->d.elg.csum = read_16(inp); pktlen -= 2; cert->d.elg.csum = read_16(inp); pktlen -= 2;
cert->d.elg.calc_csum = 0;
if( list_mode ) { if( list_mode ) {
printf("\t[secret value x is not shown]\n" printf("\t[secret value x is not shown]\n"
"\tchecksum: %04hx\n", cert->d.elg.csum); "\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 p=", cert->d.elg.p );
log_mpidump("elg g=", cert->d.elg.g ); log_mpidump("elg g=", cert->d.elg.g );
log_mpidump("elg y=", cert->d.elg.y ); log_mpidump("elg y=", cert->d.elg.y );
log_mpidump("elg x=", cert->d.elg.x ); */ log_mpidump("elg x=", cert->d.elg.x ); */
} }
} }
}
else if( algorithm == PUBKEY_ALGO_RSA ) { else if( algorithm == PUBKEY_ALGO_RSA ) {
MPI rsa_pub_mod, rsa_pub_exp; MPI rsa_pub_mod, rsa_pub_exp;
n = pktlen; rsa_pub_mod = mpi_decode(inp, &n ); pktlen -=n; n = pktlen; rsa_pub_mod = mpi_read(inp, &n, 0); pktlen -=n;
n = pktlen; rsa_pub_exp = mpi_decode(inp, &n ); pktlen -=n; n = pktlen; rsa_pub_exp = mpi_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) { if( list_mode ) {
printf( "\tpublic modulus n: "); printf( "\tpublic modulus n: ");
mpi_print(stdout, rsa_pub_mod, mpi_print_mode ); mpi_print(stdout, rsa_pub_mod, mpi_print_mode );
@ -546,36 +538,16 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
else else
cert->d.rsa.is_protected = 0; cert->d.rsa.is_protected = 0;
n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2); n = pktlen; cert->d.rsa.rsa_d = mpi_read(inp, &n, 1 ); pktlen -=n;
cert->d.rsa.rsa_d = (MPI)mpibuf; n = pktlen; cert->d.rsa.rsa_p = mpi_read(inp, &n, 1 ); pktlen -=n;
n = pktlen; cert->d.rsa.rsa_q = mpi_read(inp, &n, 1 ); pktlen -=n;
n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2); n = pktlen; cert->d.rsa.rsa_u = mpi_read(inp, &n, 1 ); pktlen -=n;
cert->d.rsa.rsa_p = (MPI)mpibuf;
n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
cert->d.rsa.rsa_q = (MPI)mpibuf;
n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
cert->d.rsa.rsa_u = (MPI)mpibuf;
cert->d.rsa.csum = read_16(inp); pktlen -= 2; cert->d.rsa.csum = read_16(inp); pktlen -= 2;
cert->d.rsa.calc_csum = 0;
if( list_mode ) { if( list_mode ) {
printf("\t[secret values d,p,q,u are not shown]\n" printf("\t[secret values d,p,q,u are not shown]\n"
"\tchecksum: %04hx\n", cert->d.rsa.csum); "\tchecksum: %04hx\n", cert->d.rsa.csum);
} }
if( !cert->d.rsa.is_protected ) { /* convert buffer to MPIs */
#define X(a) do { \
mpibuf = (byte*)cert->d.rsa.rsa_##a; \
cert->d.rsa.calc_csum += checksum( mpibuf ); \
cert->d.rsa.rsa_##a = mpi_decode_buffer( mpibuf ); \
m_free( mpibuf ); \
} while(0)
X(d);
X(p);
X(q);
X(u);
#undef X
/* log_mpidump("rsa n=", cert->d.rsa.rsa_n ); /* log_mpidump("rsa n=", cert->d.rsa.rsa_n );
log_mpidump("rsa e=", cert->d.rsa.rsa_e ); log_mpidump("rsa e=", cert->d.rsa.rsa_e );
log_mpidump("rsa d=", cert->d.rsa.rsa_d ); log_mpidump("rsa d=", cert->d.rsa.rsa_d );
@ -584,7 +556,6 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
log_mpidump("rsa u=", cert->d.rsa.rsa_u ); */ log_mpidump("rsa u=", cert->d.rsa.rsa_u ); */
} }
} }
}
else if( list_mode ) else if( list_mode )
printf("\tunknown algorithm %d\n", algorithm ); printf("\tunknown algorithm %d\n", algorithm );
@ -671,34 +642,9 @@ parse_trust( IOBUF inp, int pkttype, unsigned long pktlen )
1 = "we do not trust this key's ownership" 1 = "we do not trust this key's ownership"
2 = "we have marginal confidence of this key's ownership" 2 = "we have marginal confidence of this key's ownership"
3 = "we completely trust this key's ownership." 3 = "we completely trust this key's ownership."
/* This one (3) requires either:
* - 1 ultimately trusted signature (SIGTRUST=7)
* - COMPLETES_NEEDED completely trusted signatures (SIGTRUST=6)
* - MARGINALS_NEEDED marginally trusted signatures (SIGTRUST=5)
*/
if( c & 0x80 ) if( c & 0x80 )
"warnonly" "warnonly"
else if( prev_packet_is_a_signature ) { else if( prev_packet_is_a_signature ) {
Bits 0-2 - SIGTRUST bits - Trust bits for this signature. Value is
copied directly from OWNERTRUST bits of signer:
000 - undefined, or uninitialized trust.
001 - unknown
010 - We do not trust this signature.
011 - reserved
100 - reserved
101 - We reasonably trust this signature.
110 - We completely trust this signature.
111 - ultimately trusted signature (from the owner of the ring)
Bit 6 - CHECKED bit - This means that the key checking pass (pgp -kc,
also invoked automatically whenever keys are added to the
keyring) has tested this signature and found it good. If
this bit is not set, the maintenance pass considers this
signature untrustworthy.
Bit 7 - CONTIG bit - Means this signature leads up a contiguous trusted
certification path all the way back to the ultimately-
trusted keyring owner, where the buck stops. This bit is derived
from other trust packets. It is currently not used for anything
in PGP.
} }
#endif #endif
} }

View File

@ -44,13 +44,13 @@ get_passphrase_hash( u32 *keyid, char *text )
DEK *dek; DEK *dek;
if( keyid ) { if( keyid ) {
tty_printf("Need a pass phrase to unlock the secret key!\n"); tty_printf("\nNeed a pass phrase to unlock the secret key!\n");
tty_printf("KeyID: %08lX\n\n", keyid[1] ); tty_printf("KeyID: %08lX\n\n", keyid[1] );
} }
if( keyid && (p=getenv("PGPPATHPHRASE")) ) { if( keyid && (p=getenv("G10PASSPHRASE")) ) {
pw = m_alloc_secure(strlen(p)+1); pw = m_alloc_secure(strlen(p)+1);
strcpy(pw,p); strcpy(pw,p);
tty_printf("Taking it from $PGPPATHPHRASE !\n", keyid[1] ); tty_printf("Taking it from $G10PASSPHRASE !\n", keyid[1] );
} }
else else
pw = tty_get_hidden("Enter pass phrase: " ); pw = tty_get_hidden("Enter pass phrase: " );
@ -61,7 +61,7 @@ get_passphrase_hash( u32 *keyid, char *text )
m_free(pw); /* is allocated in secure memory, so it will be burned */ m_free(pw); /* is allocated in secure memory, so it will be burned */
if( !p ) { if( !p ) {
tty_kill_prompt(); tty_kill_prompt();
tty_printf("\n\n"); tty_printf("\n");
} }
return dek; return dek;
} }
@ -70,6 +70,7 @@ get_passphrase_hash( u32 *keyid, char *text )
/**************** /****************
* This function is used to construct a DEK from a user input. * This function is used to construct a DEK from a user input.
* It uses the default CIPHER * It uses the default CIPHER
* Returns: 0 = okay, -1 No passphrase entered, > 0 error
*/ */
int int
make_dek_from_passphrase( DEK *dek, int mode ) make_dek_from_passphrase( DEK *dek, int mode )
@ -88,6 +89,9 @@ make_dek_from_passphrase( DEK *dek, int mode )
} }
m_free(pw2); m_free(pw2);
} }
if( !*pw )
rc = -1;
else
rc = hash_passphrase( dek, pw ); rc = hash_passphrase( dek, pw );
m_free(pw); m_free(pw);
return rc; return rc;

View File

@ -35,12 +35,20 @@
#endif #endif
static u16 static u16
checksum( byte *p ) checksum_u16( unsigned n )
{ {
u16 n, a; u16 a;
a = (n >> 8) & 0xff;
a |= n & 0xff;
return a;
}
static u16
checksum( byte *p, unsigned n )
{
u16 a;
n = *p++ << 8;
n |= *p++;
for(a=0; n; n-- ) for(a=0; n; n-- )
a += *p++; a += *p++;
return a; return a;
@ -51,16 +59,16 @@ checksum( byte *p )
static int static int
check_elg( PKT_secret_cert *cert ) check_elg( PKT_secret_cert *cert )
{ {
byte iv[8]; byte *buffer;
byte *mpibuf; u16 n, csum=0;
u16 n;
MPI temp_mpi;
int res; int res;
unsigned nbytes;
u32 keyid[2]; u32 keyid[2];
ELG_secret_key skey; ELG_secret_key skey;
if( cert->d.elg.is_protected ) { /* remove the protection */ if( cert->d.elg.is_protected ) { /* remove the protection */
DEK *dek = NULL; DEK *dek = NULL;
MPI test_x;
BLOWFISH_context *blowfish_ctx=NULL; BLOWFISH_context *blowfish_ctx=NULL;
switch( cert->d.elg.protect_algo ) { switch( cert->d.elg.protect_algo ) {
@ -68,48 +76,88 @@ check_elg( PKT_secret_cert *cert )
case CIPHER_ALGO_BLOWFISH: case CIPHER_ALGO_BLOWFISH:
keyid_from_skc( cert, 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 */
memset( iv, 0, BLOWFISH_BLOCKSIZE );
blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx ); blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
blowfish_setiv( blowfish_ctx, iv ); blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
m_free(dek); /* pw is in secure memory, so m_free() burns it */
blowfish_setiv( blowfish_ctx, NULL );
blowfish_decode_cfb( blowfish_ctx, blowfish_decode_cfb( blowfish_ctx,
cert->d.elg.protect.blowfish.iv, cert->d.elg.protect.blowfish.iv,
cert->d.elg.protect.blowfish.iv, 8 ); cert->d.elg.protect.blowfish.iv, 8 );
cert->d.elg.calc_csum = 0; buffer = mpi_get_buffer( cert->d.elg.x, &nbytes, NULL );
mpibuf = (byte*)cert->d.elg.x; csum = checksum_u16( nbytes*8 );
n = ((mpibuf[0] << 8) | mpibuf[1])-2; blowfish_decode_cfb( blowfish_ctx, buffer, buffer, nbytes );
blowfish_decode_cfb( blowfish_ctx, mpibuf+4, mpibuf+4, n ); csum += checksum( buffer, nbytes );
cert->d.elg.calc_csum += checksum( mpibuf ); test_x = mpi_alloc_secure( mpi_get_nlimbs(cert->d.elg.x) );
cert->d.elg.x = mpi_decode_buffer( mpibuf ); mpi_set_buffer( test_x, buffer, nbytes, 0 );
m_free( mpibuf ); m_free( buffer );
m_free( blowfish_ctx ); m_free( blowfish_ctx );
cert->d.elg.is_protected = 0;
/* now let's see wether we have used the right passphrase */ /* now let's see wether we have used the right passphrase */
if( cert->d.elg.calc_csum != cert->d.elg.csum ) if( csum != cert->d.elg.csum ) {
mpi_free(test_x);
return G10ERR_BAD_PASS; return G10ERR_BAD_PASS;
}
skey.p = cert->d.elg.p; skey.p = cert->d.elg.p;
skey.g = cert->d.elg.g; skey.g = cert->d.elg.g;
skey.y = cert->d.elg.y; skey.y = cert->d.elg.y;
skey.x = cert->d.elg.x; skey.x = test_x;
res = elg_check_secret_key( &skey ); res = elg_check_secret_key( &skey );
memset( &skey, 0, sizeof skey ); memset( &skey, 0, sizeof skey );
if( !res ) if( !res ) {
mpi_free(test_x);
return G10ERR_BAD_PASS; return G10ERR_BAD_PASS;
}
mpi_set(cert->d.elg.x, test_x);
mpi_free(test_x);
cert->d.elg.is_protected = 0;
break; break;
default: default:
return G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */ return G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
} }
} }
/* must check the checksum here, because we didn't do it when else { /* not protected */
* parsing an unprotected certificate */ buffer = mpi_get_buffer( cert->d.elg.x, &nbytes, NULL );
if( cert->d.elg.calc_csum != cert->d.elg.csum ) { csum = checksum_u16( nbytes*8 );
log_error("checksum in secret key certificate is wrong\n"); csum += checksum( buffer, nbytes );
log_debug("stored csum=%04hx calculated csum=%04hx\n", m_free( buffer );
cert->d.elg.csum, cert->d.elg.calc_csum ); if( csum != cert->d.elg.csum )
return G10ERR_CHECKSUM; return G10ERR_CHECKSUM;
} }
return 0;
}
static int
protect_elg( PKT_secret_cert *cert, DEK *dek )
{
byte *buffer;
unsigned nbytes;
if( !cert->d.elg.is_protected ) { /* add the protection */
BLOWFISH_context *blowfish_ctx=NULL;
switch( cert->d.elg.protect_algo ) {
case CIPHER_ALGO_NONE: log_bug(NULL); break;
case CIPHER_ALGO_BLOWFISH:
blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
blowfish_setiv( blowfish_ctx, NULL );
blowfish_encode_cfb( blowfish_ctx,
cert->d.elg.protect.blowfish.iv,
cert->d.elg.protect.blowfish.iv, 8 );
buffer = mpi_get_buffer( cert->d.elg.x, &nbytes, NULL );
blowfish_encode_cfb( blowfish_ctx, buffer, buffer, nbytes );
mpi_set_buffer( cert->d.elg.x, buffer, nbytes, 0 );
m_free( buffer );
m_free( blowfish_ctx );
cert->d.elg.is_protected = 1;
break;
default:
return G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
}
}
return 0; return 0;
} }
@ -118,80 +166,86 @@ check_elg( PKT_secret_cert *cert )
static int static int
check_rsa( PKT_secret_cert *cert ) check_rsa( PKT_secret_cert *cert )
{ {
byte iv[8]; byte *buffer;
byte *mpibuf; u16 n, csum=0;
u16 n;
MPI temp_mpi;
int res; int res;
unsigned nbytes;
u32 keyid[2]; u32 keyid[2];
RSA_secret_key skey;
if( cert->d.rsa.is_protected ) { /* remove the protection */ if( cert->d.rsa.is_protected ) { /* remove the protection */
DEK *dek = NULL; DEK *dek = NULL;
BLOWFISH_context *blowfish_ctx=NULL; BLOWFISH_context *blowfish_ctx=NULL;
switch( cert->d.rsa.protect_algo ) { switch( cert->d.rsa.protect_algo ) {
case CIPHER_ALGO_NONE: /* FIXME: use test variables to check for the correct key */
log_bug("unprotect secret_cert is flagged protected\n"); case CIPHER_ALGO_NONE: log_bug(NULL); break;
break;
case CIPHER_ALGO_BLOWFISH: case CIPHER_ALGO_BLOWFISH:
keyid_from_skc( cert, 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 */
memset( iv, 0, BLOWFISH_BLOCKSIZE );
blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx ); blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
blowfish_setiv( blowfish_ctx, iv ); blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
m_free(dek); /* pw is in secure memory, so m_free() burns it */
blowfish_setiv( blowfish_ctx, NULL );
blowfish_decode_cfb( blowfish_ctx, blowfish_decode_cfb( blowfish_ctx,
cert->d.rsa.protect.blowfish.iv, cert->d.rsa.protect.blowfish.iv,
cert->d.rsa.protect.blowfish.iv, 8 ); cert->d.rsa.protect.blowfish.iv, 8 );
cert->d.rsa.calc_csum = 0; csum = 0;
#define X(a) do { \ #define X(a) do { \
mpibuf = (byte*)cert->d.rsa.rsa_##a; \ buffer = mpi_get_buffer( cert->d.rsa.rsa_##a, &nbytes, NULL );\
n = ((mpibuf[0] << 8) | mpibuf[1])-2; \ csum += checksum_u16( nbytes*8 ); \
blowfish_decode_cfb( blowfish_ctx, \ blowfish_decode_cfb( blowfish_ctx, buffer, buffer, nbytes ); \
mpibuf+4, mpibuf+4, n ); \ csum += checksum( buffer, nbytes ); \
cert->d.rsa.calc_csum += checksum( mpibuf ); \ mpi_set_buffer(cert->d.rsa.rsa_##a, buffer, nbytes, 0 ); \
cert->d.rsa.rsa_##a = mpi_decode_buffer( mpibuf ); \ m_free( buffer ); \
m_free( mpibuf ); \
} while(0) } while(0)
X(d); X(d);
X(p); X(p);
X(q); X(q);
X(u); X(u);
#undef X #undef X
m_free( blowfish_ctx );
cert->d.rsa.is_protected = 0; cert->d.rsa.is_protected = 0;
#if 0 m_free( blowfish_ctx );
#define X(a) do { printf("\tRSA " #a ": "); \
mpi_print(stdout, cert->d.rsa.rsa_##a, 1 ); \
putchar('\n'); \
} while(0)
X(n); X(e); X(d); X(p); X(q); X(u);
#undef X
#endif
/* now let's see wether we have used the right passphrase */ /* now let's see wether we have used the right passphrase */
if( cert->d.rsa.calc_csum != cert->d.rsa.csum ) if( csum != cert->d.rsa.csum )
return G10ERR_BAD_PASS; return G10ERR_BAD_PASS;
temp_mpi = mpi_alloc(40);
mpi_mul(temp_mpi, cert->d.rsa.rsa_p, cert->d.rsa.rsa_q ); skey.d = cert->d.rsa.rsa_d;
res = mpi_cmp( temp_mpi, cert->d.rsa.rsa_n ); skey.p = cert->d.rsa.rsa_p;
mpi_free(temp_mpi); skey.q = cert->d.rsa.rsa_q;
if( res ) skey.u = cert->d.rsa.rsa_u;
res = rsa_check_secret_key( &skey );
memset( &skey, 0, sizeof skey );
if( !res )
return G10ERR_BAD_PASS; return G10ERR_BAD_PASS;
break; break;
default: default:
return G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */ return G10ERR_CIPHER_ALGO; /* unsupported protection algorithm */
} }
} }
/* must check the checksum here, because we didn't do it when else { /* not protected */
* parsing an unprotected certificate */ csum =0;
if( cert->d.rsa.calc_csum != cert->d.rsa.csum ) { buffer = mpi_get_buffer( cert->d.rsa.rsa_d, &nbytes, NULL );
log_error("checksum in secret key certificate is wrong\n"); csum += checksum_u16( nbytes*8 );
log_debug("stored csum=%04hx calculated csum=%04hx\n", csum += checksum( buffer, nbytes );
cert->d.rsa.csum, cert->d.rsa.calc_csum ); m_free( buffer );
buffer = mpi_get_buffer( cert->d.rsa.rsa_p, &nbytes, NULL );
csum += checksum_u16( nbytes*8 );
csum += checksum( buffer, nbytes );
m_free( buffer );
buffer = mpi_get_buffer( cert->d.rsa.rsa_q, &nbytes, NULL );
csum += checksum_u16( nbytes*8 );
csum += checksum( buffer, nbytes );
m_free( buffer );
buffer = mpi_get_buffer( cert->d.rsa.rsa_u, &nbytes, NULL );
csum += checksum_u16( nbytes*8 );
csum += checksum( buffer, nbytes );
m_free( buffer );
if( csum != cert->d.rsa.csum )
return G10ERR_CHECKSUM; return G10ERR_CHECKSUM;
} }
return 0; return 0;
} }
#endif /*HAVE_RSA_CIPHER*/ #endif /*HAVE_RSA_CIPHER*/
@ -201,15 +255,44 @@ check_rsa( PKT_secret_cert *cert )
/**************** /****************
* Check the secret key certificate * Check the secret key certificate
* Ask up to 3 time for a correct passphrase
*/ */
int int
check_secret_key( PKT_secret_cert *cert ) check_secret_key( PKT_secret_cert *cert )
{ {
int rc = G10ERR_BAD_PASS;
int i;
for(i=0; i < 3 && rc == G10ERR_BAD_PASS; i++ ) {
if( i )
log_error("Invalid passphrase; please try again ...\n");
if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
return check_elg( cert ); rc = check_elg( cert );
#ifdef HAVE_RSA_CIPHER #ifdef HAVE_RSA_CIPHER
else if( cert->pubkey_algo == PUBKEY_ALGO_RSA ) else if( cert->pubkey_algo == PUBKEY_ALGO_RSA )
return check_rsa( cert ); rc = check_rsa( cert );
#endif
else
rc = G10ERR_PUBKEY_ALGO;
}
return rc;
}
/****************
* Protect the secret key certificate with the passphrase from DEK
*/
int
protect_secret_key( PKT_secret_cert *cert, DEK *dek )
{
if( !dek )
return 0;
if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
return protect_elg( cert, dek );
#ifdef 0 /* noy yet implemented */
else if( cert->pubkey_algo == PUBKEY_ALGO_RSA )
return protect_rsa( cert, dek );
#endif #endif
else else
return G10ERR_PUBKEY_ALGO; return G10ERR_PUBKEY_ALGO;

View File

@ -212,3 +212,5 @@ signature_check( PKT_signature *sig, MD_HANDLE *digest )
return rc; return rc;
} }

View File

@ -49,5 +49,6 @@
#define G10ERR_NI_PUBKEY 27 #define G10ERR_NI_PUBKEY 27
#define G10ERR_NI_CIPHER 28 #define G10ERR_NI_CIPHER 28
#define G10ERR_SIG_CLASS 29 #define G10ERR_SIG_CLASS 29
#define G10ERR_BAD_MPI 30
#endif /*G10_ERRORS_H*/ #endif /*G10_ERRORS_H*/

View File

@ -33,6 +33,7 @@
#define m_realloc(n,m) m_debug_realloc((n),(m), M_DBGINFO(__LINE__) ) #define m_realloc(n,m) m_debug_realloc((n),(m), M_DBGINFO(__LINE__) )
#define m_free(n) m_debug_free((n), M_DBGINFO(__LINE__) ) #define m_free(n) m_debug_free((n), M_DBGINFO(__LINE__) )
#define m_check(n) m_debug_check((n), M_DBGINFO(__LINE__) ) #define m_check(n) m_debug_check((n), M_DBGINFO(__LINE__) )
#define m_copy(a) m_debug_copy((a), M_DBGINFO(__LINE__) )
void *m_debug_alloc( size_t n, const char *info ); void *m_debug_alloc( size_t n, const char *info );
void *m_debug_alloc_clear( size_t n, const char *info ); void *m_debug_alloc_clear( size_t n, const char *info );
@ -41,6 +42,7 @@ void *m_debug_alloc_secure_clear( size_t n, const char *info );
void *m_debug_realloc( void *a, size_t n, const char *info ); void *m_debug_realloc( void *a, size_t n, const char *info );
void m_debug_free( void *p, const char *info ); void m_debug_free( void *p, const char *info );
void m_debug_check( const void *a, const char *info ); void m_debug_check( const void *a, const char *info );
void *m_debug_copy( const void *a, const char *info );
#else #else
void *m_alloc( size_t n ); void *m_alloc( size_t n );
@ -50,6 +52,7 @@ void *m_alloc_secure_clear( size_t n );
void *m_realloc( void *a, size_t n ); void *m_realloc( void *a, size_t n );
void m_free( void *p ); void m_free( void *p );
void m_check( const void *a ); void m_check( const void *a );
void *m_copy( void *a );
#endif #endif

View File

@ -52,8 +52,9 @@ int mpi_debug_mode;
typedef struct mpi_struct { typedef struct mpi_struct {
int alloced; /* array size (# of allocated limbs) */ int alloced; /* array size (# of allocated limbs) */
int nlimbs; /* number of valid limbs */ int nlimbs; /* number of valid limbs */
int nbits; /* the real number of valid bits (info only) */
int sign; /* indicates a negative number */ int sign; /* indicates a negative number */
int secure; /* array mut be allocated in secure memory space */ int secure; /* array must be allocated in secure memory space */
mpi_limb_t *d; /* array with the limbs */ mpi_limb_t *d; /* array with the limbs */
} *MPI; } *MPI;
@ -90,23 +91,18 @@ void mpi_m_check( MPI a );
void mpi_swap( MPI a, MPI b); void mpi_swap( MPI a, MPI b);
/*-- mpicoder.c --*/ /*-- mpicoder.c --*/
int mpi_encode( IOBUF out, MPI a ); int mpi_write( IOBUF out, MPI a );
int mpi_encode_csum( IOBUF out, MPI a, u16 *csum );
int mpi_write( IOBUF out, byte *a);
int mpi_write_csum( IOBUF out, byte *a, u16 *csum);
#ifdef M_DEBUG #ifdef M_DEBUG
#define mpi_decode(a,b) mpi_debug_decode((a),(b), M_DBGINFO( __LINE__ ) ) #define mpi_read(a,b,c) mpi_debug_read((a),(b),(c), M_DBGINFO( __LINE__ ) )
#define mpi_decode_buffer(a) mpi_debug_decode_buffer((a), M_DBGINFO( __LINE__ ) ) MPI mpi_debug_read(IOBUF inp, unsigned *nread, int secure, const char *info);
MPI mpi_debug_decode(IOBUF inp, unsigned *nread, const char *info);
MPI mpi_debug_decode_buffer(byte *buffer, const char *info );
#else #else
MPI mpi_decode(IOBUF inp, unsigned *nread); MPI mpi_read(IOBUF inp, unsigned *nread, int secure);
MPI mpi_decode_buffer(byte *buffer );
#endif #endif
byte *mpi_read(IOBUF inp, unsigned *ret_nread);
int mpi_fromstr(MPI val, const char *str); int mpi_fromstr(MPI val, const char *str);
int mpi_print( FILE *fp, MPI a, int mode ); int mpi_print( FILE *fp, MPI a, int mode );
u32 mpi_get_keyid( MPI a, u32 *keyid ); u32 mpi_get_keyid( MPI a, u32 *keyid );
byte *mpi_get_buffer( MPI a, unsigned *nbytes, int *sign );
void mpi_set_buffer( MPI a, const byte *buffer, unsigned nbytes, int sign );
/*-- 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 );

View File

@ -24,13 +24,13 @@
#include <assert.h> #include <assert.h>
#include "mpi.h" #include "mpi.h"
#include "mpi-internal.h"
#include "iobuf.h" #include "iobuf.h"
#include "memory.h" #include "memory.h"
#include "util.h" #include "util.h"
#ifdef M_DEBUG #ifdef M_DEBUG
#undef mpi_decode #undef mpi_read
#undef mpi_decode_buffer
#endif #endif
#define MAX_EXTERN_MPI_BITS 16384 #define MAX_EXTERN_MPI_BITS 16384
@ -39,89 +39,52 @@
* write an mpi to out. * write an mpi to out.
*/ */
int int
mpi_encode( IOBUF out, MPI a ) mpi_write( IOBUF out, MPI a )
{
u16 dummy;
return mpi_encode_csum( out, a, &dummy );
}
int
mpi_encode_csum( IOBUF out, MPI a, u16 *csum )
{ {
int i; int i;
byte c;
unsigned nbits = a->nlimbs * BITS_PER_MPI_LIMB; unsigned nbits = a->nlimbs * BITS_PER_MPI_LIMB;
mpi_limb_t limb; mpi_limb_t limb;
#if BYTES_PER_MPI_LIMB != 4 /* fixme: use a->nbits if valid */
#error Make this function work with other LIMB sizes
#endif
if( nbits > MAX_EXTERN_MPI_BITS ) if( nbits > MAX_EXTERN_MPI_BITS )
log_bug("mpi_encode: mpi too large (%u bits)\n", nbits); log_bug("mpi_encode: mpi too large (%u bits)\n", nbits);
iobuf_put(out, (c=nbits >>8) ); *csum += c; iobuf_put(out, (nbits >>8) );
iobuf_put(out, (c=nbits) ); *csum += c; iobuf_put(out, (nbits) );
for(i=a->nlimbs-1; i >= 0; i-- ) { for(i=a->nlimbs-1; i >= 0; i-- ) {
limb = a->d[i]; limb = a->d[i];
iobuf_put(out, (c=limb >> 24) ); *csum += c; #if BYTES_PER_MPI_LIMB == 4
iobuf_put(out, (c=limb >> 16) ); *csum += c; iobuf_put(out, (limb >> 24) );
iobuf_put(out, (c=limb >> 8) ); *csum += c; iobuf_put(out, (limb >> 16) );
iobuf_put(out, (c=limb ) ); *csum += c; iobuf_put(out, (limb >> 8) );
iobuf_put(out, (limb ) );
#elif BYTES_PER_MPI_LIMB == 8
iobuf_put(out, (limb >> 56) );
iobuf_put(out, (limb >> 48) );
iobuf_put(out, (limb >> 40) );
iobuf_put(out, (limb >> 32) );
iobuf_put(out, (limb >> 24) );
iobuf_put(out, (limb >> 16) );
iobuf_put(out, (limb >> 8) );
iobuf_put(out, (limb ) );
#else
#error Make this function work with other LIMB sizes
#endif
} }
return 0; return 0;
} }
/****************
* encode the MPI into a newly allocated buffer, the buffer is
* so constructed, that it can be used for mpi_write. The caller
* must free the returned buffer. The buffer is allocated in the same
* type of memory space as A is.
*/
byte *
mpi_encode_buffer( MPI a )
{
abort();
return NULL;
}
/**************** /****************
* write an mpi to out. This is a special function to handle * Read an external representation of an mpi and return the MPI
* encrypted values. It simply writes the buffer a to OUT.
* A is a special buffer, starting with 2 bytes giving it's length
* (in big endian order) and 2 bytes giving it's length in bits (also
* big endian)
*/
int
mpi_write( IOBUF out, byte *a)
{
u16 dummy;
return mpi_write_csum( out, a, &dummy );
}
int
mpi_write_csum( IOBUF out, byte *a, u16 *csum)
{
int rc;
unsigned n;
n = *a++ << 8;
n |= *a++;
rc = iobuf_write(out, a, n );
for( ; n; n--, a++ )
*csum += *a;
return rc;
}
/****************
* Decode an external representation and return an MPI
* The external format is a 16 bit unsigned value stored in network byte order, * The external format is a 16 bit unsigned value stored in network byte order,
* giving the number of bits for the following integer. The integer is stored * giving the number of bits for the following integer. The integer is stored
* with MSB first (left padded with zeroes to align on a byte boundary). * with MSB first (left padded with zeroes to align on a byte boundary).
*/ */
MPI MPI
#ifdef M_DEBUG #ifdef M_DEBUG
mpi_debug_decode(IOBUF inp, unsigned *ret_nread, const char *info) mpi_debug_read(IOBUF inp, unsigned *ret_nread, int secure, const char *info)
#else #else
mpi_decode(IOBUF inp, unsigned *ret_nread) mpi_read(IOBUF inp, unsigned *ret_nread, int secure)
#endif #endif
{ {
int c, i, j; int c, i, j;
@ -144,12 +107,15 @@ mpi_decode(IOBUF inp, unsigned *ret_nread)
nbytes = (nbits+7) / 8; nbytes = (nbits+7) / 8;
nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
#ifdef M_DEBUG #ifdef M_DEBUG
val = mpi_debug_alloc( nlimbs, info ); val = secure? mpi_debug_alloc_secure( nlimbs, info )
: mpi_debug_alloc( nlimbs, info );
#else #else
val = mpi_alloc( nlimbs ); val = secure? mpi_alloc_secure( nlimbs )
: mpi_alloc( nlimbs );
#endif #endif
i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
i %= BYTES_PER_MPI_LIMB; i %= BYTES_PER_MPI_LIMB;
val->nbits = nbits;
j= val->nlimbs = nlimbs; j= val->nlimbs = nlimbs;
val->sign = 0; val->sign = 0;
for( ; j > 0; j-- ) { for( ; j > 0; j-- ) {
@ -171,103 +137,6 @@ mpi_decode(IOBUF inp, unsigned *ret_nread)
} }
/****************
* Decode an MPI from the buffer, the buffer starts with two bytes giving
* the length of the data to follow, the original data follows.
* The MPI is alloced from secure MPI space
*/
MPI
#ifdef M_DEBUG
mpi_debug_decode_buffer(byte *buffer, const char *info )
#else
mpi_decode_buffer(byte *buffer )
#endif
{
int i, j;
u16 buflen;
unsigned nbits, nbytes, nlimbs;
mpi_limb_t a;
byte *p = buffer;
MPI val;
if( !buffer )
log_bug("mpi_decode_buffer: no buffer\n");
buflen = *p++ << 8;
buflen |= *p++;
nbits = *p++ << 8;
nbits |= *p++;
nbytes = (nbits+7) / 8;
if( nbytes+2 != buflen )
log_bug("mpi_decode_buffer: length conflict\n");
nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
#ifdef M_DEBUG
val = mpi_debug_alloc_secure( nlimbs, info );
#else
val = mpi_alloc_secure( nlimbs );
#endif
i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
i %= BYTES_PER_MPI_LIMB;
j= val->nlimbs = nlimbs;
val->sign = 0;
for( ; j > 0; j-- ) {
a = 0;
for(; i < BYTES_PER_MPI_LIMB; i++ ) {
a <<= 8;
a |= *p++;
}
i = 0;
val->d[j-1] = a;
}
return val;
}
/****************
* Read a MPI from the external medium and return it in a newly allocated
* buffer (This buffer is allocated in the secure memory space, because
* we properly need this to decipher this string).
* Return: the allocated string and in RET_NREAD the number of bytes
* read (including the 2 length bytes), the returned buffer will
* be prefixed with two bytes describing the length of the following
* data.
*/
byte *
mpi_read(IOBUF inp, unsigned *ret_nread)
{
int c;
u16 buflen;
unsigned nbits, nbytes, nread;
byte *p, *buf;
if( (c = iobuf_get(inp)) == -1 )
return NULL;
nbits = c << 8;
if( (c = iobuf_get(inp)) == -1 )
return NULL;
nbits |= c;
if( nbits > MAX_EXTERN_MPI_BITS ) {
log_error("mpi too large (%u bits)\n", nbits);
return NULL;
}
nread = 2;
nbytes = (nbits+7) / 8;
buflen = nbytes + 2;
p = buf = m_alloc_secure( buflen+2 );
*p++ = buflen >> 8;
*p++ = buflen & 0xff;
*p++ = nbits >> 8;
*p++ = nbits & 0xff;
for( ; nbytes ; nbytes--, nread++ )
*p++ = iobuf_get(inp) & 0xff;
if( nread > *ret_nread )
log_error("Ooops: mpi crosses packet border");
else
*ret_nread = nread;
return buf;
}
/**************** /****************
* Make a mpi from a character string. * Make a mpi from a character string.
@ -390,3 +259,96 @@ mpi_get_keyid( MPI a, u32 *keyid )
} }
/****************
* Return a m_alloced buffer with the MPI (msb first).
* NBYTES receives the length of this buffer. Caller must free the
* return string (This function does return a 0 byte buffer with NBYTES
* set to zero if the value of A is zero. If sign is not NULL, it will
* be set to the sign of the A.
*/
byte *
mpi_get_buffer( MPI a, unsigned *nbytes, int *sign )
{
byte *p, *buffer;
mpi_limb_t alimb;
int i;
if( sign )
*sign = a->sign;
*nbytes = a->nlimbs * BYTES_PER_MPI_LIMB;
p = buffer = a->secure ? m_alloc_secure( *nbytes) : m_alloc( *nbytes );
for(i=a->nlimbs-1; i >= 0; i-- ) {
alimb = a->d[i];
#if BYTES_PER_MPI_LIMB == 4
*p++ = alimb >> 24;
*p++ = alimb >> 16;
*p++ = alimb >> 8;
*p++ = alimb ;
#elif BYTES_PER_MPI_LIMB == 8
*p++ = alimb >> 56;
*p++ = alimb >> 48;
*p++ = alimb >> 40;
*p++ = alimb >> 32;
*p++ = alimb >> 24;
*p++ = alimb >> 16;
*p++ = alimb >> 8;
*p++ = alimb ;
#else
#error please implement for this limb size.
#endif
}
return buffer;
}
/****************
* Use BUFFER to update MPI.
*/
void
mpi_set_buffer( MPI a, const byte *buffer, unsigned nbytes, int sign )
{
const byte *p;
mpi_limb_t alimb;
int nlimbs;
int i;
nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
RESIZE_IF_NEEDED(a, nlimbs);
a->sign = sign;
for(i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; ) {
#if BYTES_PER_MPI_LIMB == 4
alimb = *p-- ;
alimb |= *p-- << 8 ;
alimb |= *p-- << 16 ;
alimb |= *p-- << 24 ;
#elif BYTES_PER_MPI_LIMB == 8
#else
#error please implement for this limb size.
#endif
a->d[i++] = alimb;
}
if( p >= buffer ) {
#if BYTES_PER_MPI_LIMB == 4
alimb = *p-- ;
if( p >= buffer ) alimb |= *p-- << 8 ;
if( p >= buffer ) alimb |= *p-- << 16 ;
if( p >= buffer ) alimb |= *p-- << 24 ;
#elif BYTES_PER_MPI_LIMB == 8
alimb = *p-- ;
if( p >= buffer ) alimb |= *p-- << 8 ;
if( p >= buffer ) alimb |= *p-- << 16 ;
if( p >= buffer ) alimb |= *p-- << 24 ;
if( p >= buffer ) alimb |= *p-- << 32 ;
if( p >= buffer ) alimb |= *p-- << 40 ;
if( p >= buffer ) alimb |= *p-- << 48 ;
if( p >= buffer ) alimb |= *p-- << 56 ;
#else
#error please implement for this limb size.
#endif
a->d[i++] = alimb;
}
a->nlimbs = i;
assert( i == nlimbs );
}

View File

@ -456,3 +456,26 @@ m_is_secure( const void *p )
return p && ((byte*)p)[-1] == MAGIC_SEC_BYTE; return p && ((byte*)p)[-1] == MAGIC_SEC_BYTE;
} }
/****************
* Make a copy of the memory block at a
*/
void *
FNAME(copy)( void *a FNAMEPRT )
{
void *b;
size_t n;
if( !a )
return a;
n = m_size(a);
if( m_is_secure(a) )
b = FNAME(alloc_secure)(n FNAMEARG);
else
b = FNAME(alloc)(n FNAMEARG);
memcpy(b, a, n );
return b;
}