aboutsummaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
Diffstat (limited to 'g10')
-rw-r--r--g10/build-packet.c86
-rw-r--r--g10/free-packet.c21
-rw-r--r--g10/g10.c14
-rw-r--r--g10/keydb.h2
-rw-r--r--g10/keygen.c200
-rw-r--r--g10/keyid.c107
-rw-r--r--g10/mainproc.c43
-rw-r--r--g10/options.h4
-rw-r--r--g10/packet.h8
-rw-r--r--g10/parse-packet.c108
-rw-r--r--g10/passphrase.c14
-rw-r--r--g10/seckey-cert.c237
-rw-r--r--g10/sig-check.c2
13 files changed, 593 insertions, 253 deletions
diff --git a/g10/build-packet.c b/g10/build-packet.c
index 6d9957f17..25d708ceb 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -169,13 +169,13 @@ do_public_cert( IOBUF out, int ctb, PKT_public_cert *pkc )
write_16(a, pkc->valid_days );
iobuf_put(a, pkc->pubkey_algo );
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 );
+ mpi_write(a, pkc->d.elg.p );
+ mpi_write(a, pkc->d.elg.g );
+ mpi_write(a, pkc->d.elg.y );
}
else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
- mpi_encode(a, pkc->d.rsa.rsa_n );
- mpi_encode(a, pkc->d.rsa.rsa_e );
+ mpi_write(a, pkc->d.rsa.rsa_n );
+ mpi_write(a, pkc->d.rsa.rsa_e );
}
else {
rc = G10ERR_PUBKEY_ALGO;
@@ -191,6 +191,31 @@ do_public_cert( IOBUF out, int ctb, PKT_public_cert *pkc )
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
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 );
iobuf_put(a, skc->pubkey_algo );
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 );
+ mpi_write(a, skc->d.elg.p );
+ mpi_write(a, skc->d.elg.g );
+ mpi_write(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 );
+ mpi_write(a, skc->d.elg.x );
+ write_16(a, skc->d.elg.csum );
}
else if( skc->pubkey_algo == PUBKEY_ALGO_RSA ) {
- mpi_encode(a, skc->d.rsa.rsa_n );
- mpi_encode(a, skc->d.rsa.rsa_e );
+ mpi_write(a, skc->d.rsa.rsa_n );
+ mpi_write(a, skc->d.rsa.rsa_e );
iobuf_put(a, skc->d.rsa.protect_algo );
- skc->d.rsa.calc_csum = 0;
if( skc->d.rsa.protect_algo ) {
assert( skc->d.rsa.is_protected == 1 );
assert( skc->d.rsa.protect_algo == CIPHER_ALGO_BLOWFISH );
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! */
- assert( !skc->d.rsa.is_protected );
- mpi_encode_csum(a, skc->d.rsa.rsa_d, &skc->d.rsa.calc_csum );
- mpi_encode_csum(a, skc->d.rsa.rsa_p, &skc->d.rsa.calc_csum );
- mpi_encode_csum(a, skc->d.rsa.rsa_q, &skc->d.rsa.calc_csum );
- mpi_encode_csum(a, skc->d.rsa.rsa_u, &skc->d.rsa.calc_csum );
}
-
- write_16(a, skc->d.rsa.calc_csum );
+ mpi_write(a, skc->d.rsa.rsa_d );
+ mpi_write(a, skc->d.rsa.rsa_p );
+ mpi_write(a, skc->d.rsa.rsa_q );
+ mpi_write(a, skc->d.rsa.rsa_u );
+ write_16(a, skc->d.rsa.csum );
}
else {
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] );
iobuf_put(a,enc->pubkey_algo );
if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
- mpi_encode(a, enc->d.elg.a );
- mpi_encode(a, enc->d.elg.b );
+ mpi_write(a, enc->d.elg.a );
+ mpi_write(a, enc->d.elg.b );
}
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 {
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_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 );
+ mpi_write(a, sig->d.elg.a );
+ mpi_write(a, sig->d.elg.b );
}
else if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) {
iobuf_put(a, sig->d.rsa.digest_algo );
iobuf_put(a, sig->d.rsa.digest_start[0] );
iobuf_put(a, sig->d.rsa.digest_start[1] );
- mpi_encode(a, sig->d.rsa.rsa_integer );
+ mpi_write(a, sig->d.rsa.rsa_integer );
}
else {
rc = G10ERR_PUBKEY_ALGO;
diff --git a/g10/free-packet.c b/g10/free-packet.c
index fa116ba62..dfd6f4b08 100644
--- a/g10/free-packet.c
+++ b/g10/free-packet.c
@@ -100,26 +100,15 @@ free_secret_cert( PKT_secret_cert *cert )
mpi_free( cert->d.elg.p );
mpi_free( cert->d.elg.g );
mpi_free( cert->d.elg.y );
- if( cert->d.rsa.is_protected )
- m_free( cert->d.elg.x );
- else
- mpi_free( cert->d.elg.x );
+ mpi_free( cert->d.elg.x );
}
else if( cert->pubkey_algo == PUBKEY_ALGO_RSA ) {
mpi_free( cert->d.rsa.rsa_n );
mpi_free( cert->d.rsa.rsa_e );
- if( cert->d.rsa.is_protected ) {
- m_free( cert->d.rsa.rsa_d );
- m_free( cert->d.rsa.rsa_p );
- m_free( cert->d.rsa.rsa_q );
- m_free( cert->d.rsa.rsa_u );
- }
- else {
- mpi_free( cert->d.rsa.rsa_d );
- mpi_free( cert->d.rsa.rsa_p );
- mpi_free( cert->d.rsa.rsa_q );
- mpi_free( cert->d.rsa.rsa_u );
- }
+ 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);
}
diff --git a/g10/g10.c b/g10/g10.c
index 747cba196..88bde47cc 100644
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -124,6 +124,8 @@ main( int argc, char **argv )
{ 512, "cache-all" ,0, "hold everything in memory"},
{ 513, "gen-prime" , 1, "\rgenerate a prime of length n" },
{ 514, "test" , 0, "\rdevelopment usage" },
+ { 515, "change-passphrase", 0, "change the passphrase of your secret keyring"},
+ { 515, "fingerprint", 0, "show the fingerprints"},
{0} };
ARGPARSE_ARGS pargs = { &argc, &argv, 0 };
IOBUF a;
@@ -136,11 +138,14 @@ main( int argc, char **argv )
int nrings=0;
armor_filter_context_t afx;
const char *s;
+ int detached_sig = 0;
opt.compress = -1; /* defaults to default compression level */
while( arg_parse( &pargs, opts) ) {
switch( pargs.r_opt ) {
- case 'v': opt.verbose++; break;
+ case 'v': opt.verbose++;
+ opt.list_sigs=1;
+ break;
case 'z':
opt.compress = pargs.r.ret_int;
break;
@@ -151,7 +156,7 @@ main( int argc, char **argv )
opt.outfile_is_stdout = 1;
break;
case 'e': action = action == aSign? aSignEncr : aEncr; break;
- case 'b': opt.detached_sig = 1;
+ case 'b': detached_sig = 1;
/* fall trough */
case 's': action = action == aEncr? aSignEncr : aSign; break;
case 'l': /* store the local users */
@@ -171,13 +176,14 @@ main( int argc, char **argv )
case 502: opt.answer_no = 1; break;
case 503: action = aKeygen; 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 510: opt.debug |= pargs.r.ret_ulong; break;
case 511: opt.debug = ~0; break;
case 512: opt.cache_all = 1; break;
case 513: action = aPrimegen; break;
case 514: action = aTest; break;
+ case 515: opt.fingerprint = 1; break;
default : pargs.err = 2; break;
}
}
@@ -230,7 +236,7 @@ main( int argc, char **argv )
case aSign: /* sign the given file */
if( argc > 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) );
break;
diff --git a/g10/keydb.h b/g10/keydb.h
index 21423cfbb..bd8928086 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -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_skc( PKT_secret_cert *skc );
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 );
diff --git a/g10/keygen.c b/g10/keygen.c
index 3cbbf89e1..a4ed697c4 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -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
-write_uid( IOBUF out, const char *s )
+write_uid( IOBUF out, const char *s, PKT_user_id **upkt )
{
PACKET pkt;
size_t n = strlen(s);
@@ -65,13 +100,44 @@ write_uid( IOBUF out, const char *s )
strcpy(pkt.pkt.user_id->name, s);
if( (rc = build_packet( out, &pkt )) )
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 );
}
+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
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;
PACKET pkt1, pkt2;
@@ -80,6 +146,9 @@ gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
RSA_public_key pk;
RSA_secret_key sk;
+ init_packet(&pkt1);
+ init_packet(&pkt2);
+
rsa_generate( &pk, &sk, nbits );
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_q = sk.q;
skc->d.rsa.rsa_u = sk.u;
- skc->d.rsa.calc_csum = 0;
- skc->d.rsa.is_protected = 0; /* FIXME!!! */
- skc->d.rsa.protect_algo = 0; /* should be blowfish */
- /*memcpy(skc->d.rsa.protect.blowfish.iv,"12345678", 8);*/
+ skc->d.rsa.csum = checksum_mpi( skc->d.rsa.rsa_d );
+ skc->d.rsa.csum += checksum_mpi( skc->d.rsa.rsa_p );
+ skc->d.rsa.csum += checksum_mpi( skc->d.rsa.rsa_q );
+ 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.pkt.public_cert = pkc;
- init_packet(&pkt2);
pkt2.pkttype = PKT_SECRET_CERT;
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) );
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:
free_packet(&pkt1);
@@ -125,14 +211,19 @@ gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io)
#endif /*HAVE_RSA_CIPHER*/
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;
PACKET pkt1, pkt2;
- PKT_secret_cert *skc;
+ PKT_secret_cert *skc, *unprotected_skc;
PKT_public_cert *pkc;
ELG_public_key pk;
ELG_secret_key sk;
+ unsigned nbytes;
+
+ init_packet(&pkt1);
+ init_packet(&pkt2);
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.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);*/
+ skc->d.elg.csum = checksum_mpi( skc->d.elg.x );
+ unprotected_skc = copy_secret_cert( NULL, skc );
+ if( !dek ) {
+ 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.pkt.public_cert = pkc;
- init_packet(&pkt2);
pkt2.pkttype = PKT_SECRET_CERT;
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) );
goto leave;
}
+ *ret_pkc = pkt1.pkt.public_cert;
+ pkt1.pkt.public_cert = NULL;
+ *ret_skc = unprotected_skc;
+ unprotected_skc = NULL;
+
leave:
free_packet(&pkt1);
free_packet(&pkt2);
+ if( unprotected_skc )
+ free_secret_cert( unprotected_skc );
return rc;
}
@@ -192,6 +300,10 @@ generate_keypair()
char *uid = NULL;
IOBUF pub_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 algo;
const char *algo_name;
@@ -301,6 +413,28 @@ generate_keypair()
}
}
#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 */
if( !(rc=overwrite_filep( pub_fname )) ) {
if( !(pub_io = iobuf_create( pub_fname )) )
@@ -334,23 +468,41 @@ generate_keypair()
return;
}
-
write_comment( pub_io, "#public key created by G10 pre-release " VERSION );
write_comment( sec_io, "#secret key created by G10 pre-release " VERSION );
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
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
else
log_bug(NULL);
- write_uid(pub_io, uid );
- write_uid(sec_io, uid );
+ if( !rc )
+ write_uid(pub_io, uid, &upkt );
+ 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(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);
-
- iobuf_close(pub_io);
- iobuf_close(sec_io);
+ m_free(dek);
}
diff --git a/g10/keyid.c b/g10/keyid.c
index 7453754a2..e3a16d86b 100644
--- a/g10/keyid.c
+++ b/g10/keyid.c
@@ -171,3 +171,110 @@ datestr_from_sig( PKT_signature *sig )
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;
+}
+
+
+
diff --git a/g10/mainproc.c b/g10/mainproc.c
index 9418da4e4..a04b0fc1f 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -342,7 +342,7 @@ proc_plaintext( CTX c, PACKET *pkt )
printf("txt: plain text data name='%.*s'\n", pt->namelen, pt->name);
free_md_filter_context( &c->mfx );
/* 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);
result = handle_plaintext( pt, &c->mfx );
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
*/
@@ -478,6 +506,8 @@ list_node( CTX c, NODE node )
printf( "%*s", 31, "" );
print_userid( n2->pkt );
putchar('\n');
+ if( opt.fingerprint && n2 == node->child )
+ print_fingerprint( pkc, NULL );
list_node(c, n2 );
}
}
@@ -491,18 +521,20 @@ list_node( CTX c, NODE node )
datestr_from_skc( skc ) );
n2 = node->child;
if( !n2 )
- printf("ERROR: no user id!");
+ printf("ERROR: no user id!\n");
else {
print_userid( n2->pkt );
+ putchar('\n');
+ if( opt.fingerprint && n2 == node->child )
+ print_fingerprint( NULL, skc );
}
- putchar('\n');
}
else if( node->pkt->pkttype == PKT_USER_ID ) {
/* list everything under this user id */
for(n2=node->child; n2; n2 = n2->next )
list_node(c, n2 );
}
- else if( node->pkt->pkttype == PKT_SIGNATURE ) {
+ else if( node->pkt->pkttype == PKT_SIGNATURE ) {
PKT_signature *sig = node->pkt->pkt.signature;
int rc2;
size_t n;
@@ -510,6 +542,9 @@ list_node( CTX c, NODE node )
int sigrc = ' ';
assert( !node->child );
+ if( !opt.list_sigs )
+ return;
+
if( opt.check_sigs ) {
switch( (rc2=do_check_sig( c, node )) ) {
diff --git a/g10/options.h b/g10/options.h
index 2b65db20c..a23412fc8 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -32,8 +32,8 @@ struct {
int answer_no; /* answer no on most questions */
int check_sigs; /* check key signatures */
int cache_all;
- int detached_sig;
- int reserved3;
+ int fingerprint; /* list fingerprints */
+ int list_sigs; /* list signatures */
int reserved4;
int reserved5;
int reserved6;
diff --git a/g10/packet.h b/g10/packet.h
index 5694c8a5b..57adebe5f 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -124,7 +124,6 @@ typedef struct {
MPI rsa_q; /* secret second prime number */
MPI rsa_u; /* secret multiplicative inverse */
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 decrypteded before use */
byte protect_algo; /* cipher used to protect the secret informations*/
@@ -142,7 +141,6 @@ typedef struct {
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 decrypteded before use */
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 --*/
int build_packet( IOBUF inp, PACKET *pkt );
u32 calc_packet_length( PACKET *pkt );
+void hash_public_cert( MD_HANDLE *md, PKT_public_cert *pkc );
/*-- free-packet.c --*/
void free_pubkey_enc( PKT_pubkey_enc *enc );
@@ -238,6 +237,7 @@ int signature_check( PKT_signature *sig, MD_HANDLE *digest );
/*-- seckey-cert.c --*/
int check_secret_key( PKT_secret_cert *cert );
+int protect_secret_key( PKT_secret_cert *cert, DEK *dek );
/*-- pubkey-enc.c --*/
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 --*/
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*/
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index 6aef1b4fe..5badb0ec4 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -239,8 +239,8 @@ parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
k->keyid[0], k->keyid[1]);
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;
+ k->d.elg.a = mpi_read(inp, &n, 0); pktlen -=n;
+ k->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) {
printf("\telg a: ");
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 ) {
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 ) {
printf("\trsa integer: ");
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[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;
+ sig->d.elg.a = mpi_read(inp, &n, 0 ); pktlen -=n;
+ sig->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) {
printf("\tdigest algo %d, begin of digest %02x %02x\n",
sig->d.elg.digest_algo,
@@ -313,7 +313,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
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 );
+ mpi_print(stdout, sig->d.elg.b, mpi_print_mode );
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[1] = iobuf_get_noeof(inp); 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 ) {
printf("\tdigest algo %d, begin of digest %02x %02x\n",
sig->d.rsa.digest_algo,
@@ -439,9 +439,9 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
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;
+ n = pktlen; elg_p = mpi_read(inp, &n, 0 ); pktlen -=n;
+ n = pktlen; elg_g = mpi_read(inp, &n, 0 ); pktlen -=n;
+ n = pktlen; elg_y = mpi_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) {
printf( "\telg p: ");
mpi_print(stdout, elg_p, mpi_print_mode );
@@ -483,32 +483,24 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
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;
+ n = pktlen; cert->d.elg.x = mpi_read(inp, &n, 1 ); pktlen -=n;
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 ); */
- }
+ /*log_mpidump("elg p=", cert->d.elg.p );
+ log_mpidump("elg g=", cert->d.elg.g );
+ log_mpidump("elg y=", cert->d.elg.y );
+ log_mpidump("elg x=", cert->d.elg.x ); */
}
}
else if( algorithm == PUBKEY_ALGO_RSA ) {
MPI rsa_pub_mod, rsa_pub_exp;
- n = pktlen; rsa_pub_mod = mpi_decode(inp, &n ); pktlen -=n;
- n = pktlen; rsa_pub_exp = mpi_decode(inp, &n ); pktlen -=n;
+ n = pktlen; rsa_pub_mod = mpi_read(inp, &n, 0); pktlen -=n;
+ n = pktlen; rsa_pub_exp = mpi_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) {
printf( "\tpublic modulus n: ");
mpi_print(stdout, rsa_pub_mod, mpi_print_mode );
@@ -546,43 +538,22 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
else
cert->d.rsa.is_protected = 0;
- n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
- cert->d.rsa.rsa_d = (MPI)mpibuf;
-
- n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
- 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;
+ n = pktlen; cert->d.rsa.rsa_d = mpi_read(inp, &n, 1 ); pktlen -=n;
+ 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; cert->d.rsa.rsa_u = mpi_read(inp, &n, 1 ); pktlen -=n;
cert->d.rsa.csum = read_16(inp); pktlen -= 2;
- cert->d.rsa.calc_csum = 0;
if( list_mode ) {
printf("\t[secret values d,p,q,u are not shown]\n"
"\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 e=", cert->d.rsa.rsa_e );
- log_mpidump("rsa d=", cert->d.rsa.rsa_d );
- log_mpidump("rsa p=", cert->d.rsa.rsa_p );
- log_mpidump("rsa q=", cert->d.rsa.rsa_q );
- log_mpidump("rsa u=", cert->d.rsa.rsa_u ); */
- }
+ /* log_mpidump("rsa n=", cert->d.rsa.rsa_n );
+ log_mpidump("rsa e=", cert->d.rsa.rsa_e );
+ log_mpidump("rsa d=", cert->d.rsa.rsa_d );
+ log_mpidump("rsa p=", cert->d.rsa.rsa_p );
+ log_mpidump("rsa q=", cert->d.rsa.rsa_q );
+ log_mpidump("rsa u=", cert->d.rsa.rsa_u ); */
}
}
else if( list_mode )
@@ -671,34 +642,9 @@ parse_trust( IOBUF inp, int pkttype, unsigned long pktlen )
1 = "we do not trust this key's ownership"
2 = "we have marginal confidence of 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 )
"warnonly"
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
}
diff --git a/g10/passphrase.c b/g10/passphrase.c
index 5a45f49bd..4e5e57bb3 100644
--- a/g10/passphrase.c
+++ b/g10/passphrase.c
@@ -44,13 +44,13 @@ get_passphrase_hash( u32 *keyid, char *text )
DEK *dek;
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] );
}
- if( keyid && (p=getenv("PGPPATHPHRASE")) ) {
+ if( keyid && (p=getenv("G10PASSPHRASE")) ) {
pw = m_alloc_secure(strlen(p)+1);
strcpy(pw,p);
- tty_printf("Taking it from $PGPPATHPHRASE !\n", keyid[1] );
+ tty_printf("Taking it from $G10PASSPHRASE !\n", keyid[1] );
}
else
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 */
if( !p ) {
tty_kill_prompt();
- tty_printf("\n\n");
+ tty_printf("\n");
}
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.
* It uses the default CIPHER
+ * Returns: 0 = okay, -1 No passphrase entered, > 0 error
*/
int
make_dek_from_passphrase( DEK *dek, int mode )
@@ -88,7 +89,10 @@ make_dek_from_passphrase( DEK *dek, int mode )
}
m_free(pw2);
}
- rc = hash_passphrase( dek, pw );
+ if( !*pw )
+ rc = -1;
+ else
+ rc = hash_passphrase( dek, pw );
m_free(pw);
return rc;
}
diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c
index 689f473c9..85d93b4f9 100644
--- a/g10/seckey-cert.c
+++ b/g10/seckey-cert.c
@@ -35,12 +35,20 @@
#endif
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-- )
a += *p++;
return a;
@@ -51,16 +59,16 @@ checksum( byte *p )
static int
check_elg( PKT_secret_cert *cert )
{
- byte iv[8];
- byte *mpibuf;
- u16 n;
- MPI temp_mpi;
+ byte *buffer;
+ u16 n, csum=0;
int res;
+ unsigned nbytes;
u32 keyid[2];
ELG_secret_key skey;
if( cert->d.elg.is_protected ) { /* remove the protection */
DEK *dek = NULL;
+ MPI test_x;
BLOWFISH_context *blowfish_ctx=NULL;
switch( cert->d.elg.protect_algo ) {
@@ -68,47 +76,87 @@ check_elg( PKT_secret_cert *cert )
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_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,
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 );
+ buffer = mpi_get_buffer( cert->d.elg.x, &nbytes, NULL );
+ csum = checksum_u16( nbytes*8 );
+ blowfish_decode_cfb( blowfish_ctx, buffer, buffer, nbytes );
+ csum += checksum( buffer, nbytes );
+ test_x = mpi_alloc_secure( mpi_get_nlimbs(cert->d.elg.x) );
+ mpi_set_buffer( test_x, buffer, nbytes, 0 );
+ m_free( buffer );
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 )
+ if( csum != cert->d.elg.csum ) {
+ mpi_free(test_x);
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;
+ skey.x = test_x;
res = elg_check_secret_key( &skey );
memset( &skey, 0, sizeof skey );
- if( !res )
+ if( !res ) {
+ mpi_free(test_x);
return G10ERR_BAD_PASS;
+ }
+ mpi_set(cert->d.elg.x, test_x);
+ mpi_free(test_x);
+ cert->d.elg.is_protected = 0;
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;
+ else { /* not protected */
+ buffer = mpi_get_buffer( cert->d.elg.x, &nbytes, NULL );
+ csum = checksum_u16( nbytes*8 );
+ csum += checksum( buffer, nbytes );
+ m_free( buffer );
+ if( csum != cert->d.elg.csum )
+ 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;
}
@@ -118,80 +166,86 @@ check_elg( PKT_secret_cert *cert )
static int
check_rsa( PKT_secret_cert *cert )
{
- byte iv[8];
- byte *mpibuf;
- u16 n;
- MPI temp_mpi;
+ byte *buffer;
+ u16 n, csum=0;
int res;
+ unsigned nbytes;
u32 keyid[2];
+ RSA_secret_key skey;
if( cert->d.rsa.is_protected ) { /* remove the protection */
DEK *dek = NULL;
BLOWFISH_context *blowfish_ctx=NULL;
switch( cert->d.rsa.protect_algo ) {
- case CIPHER_ALGO_NONE:
- log_bug("unprotect secret_cert is flagged protected\n");
- break;
+ /* FIXME: use test variables to check for the correct key */
+ 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_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,
cert->d.rsa.protect.blowfish.iv,
cert->d.rsa.protect.blowfish.iv, 8 );
- cert->d.rsa.calc_csum = 0;
- #define X(a) do { \
- mpibuf = (byte*)cert->d.rsa.rsa_##a; \
- n = ((mpibuf[0] << 8) | mpibuf[1])-2; \
- blowfish_decode_cfb( blowfish_ctx, \
- mpibuf+4, mpibuf+4, n ); \
- cert->d.rsa.calc_csum += checksum( mpibuf ); \
- cert->d.rsa.rsa_##a = mpi_decode_buffer( mpibuf ); \
- m_free( mpibuf ); \
- } while(0)
+ csum = 0;
+ #define X(a) do { \
+ buffer = mpi_get_buffer( cert->d.rsa.rsa_##a, &nbytes, NULL );\
+ csum += checksum_u16( nbytes*8 ); \
+ blowfish_decode_cfb( blowfish_ctx, buffer, buffer, nbytes ); \
+ csum += checksum( buffer, nbytes ); \
+ mpi_set_buffer(cert->d.rsa.rsa_##a, buffer, nbytes, 0 ); \
+ m_free( buffer ); \
+ } while(0)
X(d);
X(p);
X(q);
X(u);
- #undef X
- m_free( blowfish_ctx );
- cert->d.rsa.is_protected = 0;
- #if 0
- #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
+ cert->d.rsa.is_protected = 0;
+ m_free( blowfish_ctx );
/* 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;
- temp_mpi = mpi_alloc(40);
- mpi_mul(temp_mpi, cert->d.rsa.rsa_p, cert->d.rsa.rsa_q );
- res = mpi_cmp( temp_mpi, cert->d.rsa.rsa_n );
- mpi_free(temp_mpi);
- if( res )
+
+ skey.d = cert->d.rsa.rsa_d;
+ skey.p = cert->d.rsa.rsa_p;
+ skey.q = cert->d.rsa.rsa_q;
+ skey.u = cert->d.rsa.rsa_u;
+ res = rsa_check_secret_key( &skey );
+ memset( &skey, 0, sizeof skey );
+ if( !res )
return G10ERR_BAD_PASS;
break;
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
- * parsing an unprotected certificate */
- if( cert->d.rsa.calc_csum != cert->d.rsa.csum ) {
- log_error("checksum in secret key certificate is wrong\n");
- log_debug("stored csum=%04hx calculated csum=%04hx\n",
- cert->d.rsa.csum, cert->d.rsa.calc_csum );
- return G10ERR_CHECKSUM;
+ else { /* not protected */
+ csum =0;
+ buffer = mpi_get_buffer( cert->d.rsa.rsa_d, &nbytes, NULL );
+ csum += checksum_u16( nbytes*8 );
+ csum += checksum( buffer, nbytes );
+ 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 0;
}
#endif /*HAVE_RSA_CIPHER*/
@@ -201,15 +255,44 @@ check_rsa( PKT_secret_cert *cert )
/****************
* Check the secret key certificate
+ * Ask up to 3 time for a correct passphrase
*/
int
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 )
+ rc = check_elg( cert );
+ #ifdef HAVE_RSA_CIPHER
+ else if( cert->pubkey_algo == PUBKEY_ALGO_RSA )
+ 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 check_elg( cert );
- #ifdef HAVE_RSA_CIPHER
+ return protect_elg( cert, dek );
+ #ifdef 0 /* noy yet implemented */
else if( cert->pubkey_algo == PUBKEY_ALGO_RSA )
- return check_rsa( cert );
+ return protect_rsa( cert, dek );
#endif
else
return G10ERR_PUBKEY_ALGO;
diff --git a/g10/sig-check.c b/g10/sig-check.c
index 841423878..d5f0afb9e 100644
--- a/g10/sig-check.c
+++ b/g10/sig-check.c
@@ -212,3 +212,5 @@ signature_check( PKT_signature *sig, MD_HANDLE *digest )
return rc;
}
+
+