mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-02 22:46:30 +02:00
fingerprints and self signatures added
This commit is contained in:
parent
3b1b6f9d98
commit
935965049d
23 changed files with 783 additions and 444 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
14
g10/g10.c
14
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;
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
||||
|
||||
|
|
200
g10/keygen.c
200
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 );
|
||||
m_free(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 );
|
||||
|
||||
iobuf_close(pub_io);
|
||||
iobuf_close(sec_io);
|
||||
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);
|
||||
m_free(dek);
|
||||
}
|
||||
|
||||
|
|
107
g10/keyid.c
107
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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 )) ) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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*/
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -212,3 +212,5 @@ signature_check( PKT_signature *sig, MD_HANDLE *digest )
|
|||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue