diff options
author | Werner Koch <wk@gnupg.org> | 1998-05-26 15:38:00 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 1998-05-26 15:38:00 +0200 |
commit | eed2faab53f859c98bf85f1e324614da640bf3ff (patch) | |
tree | 4a701250cb3300121456599f90cd7a22e03e8b59 /g10 | |
parent | new release (diff) | |
download | gnupg2-eed2faab53f859c98bf85f1e324614da640bf3ff.tar.xz gnupg2-eed2faab53f859c98bf85f1e324614da640bf3ff.zip |
add-key works
Diffstat (limited to 'g10')
-rw-r--r-- | g10/ChangeLog | 32 | ||||
-rw-r--r-- | g10/armor.c | 9 | ||||
-rw-r--r-- | g10/build-packet.c | 2 | ||||
-rw-r--r-- | g10/compress.c | 6 | ||||
-rw-r--r-- | g10/encode.c | 24 | ||||
-rw-r--r-- | g10/g10.c | 5 | ||||
-rw-r--r-- | g10/gpgd.c | 7 | ||||
-rw-r--r-- | g10/import.c | 25 | ||||
-rw-r--r-- | g10/keydb.h | 2 | ||||
-rw-r--r-- | g10/keyedit.c | 63 | ||||
-rw-r--r-- | g10/keygen.c | 387 | ||||
-rw-r--r-- | g10/ks-proto.c | 246 | ||||
-rw-r--r-- | g10/packet.h | 3 | ||||
-rw-r--r-- | g10/passphrase.c | 43 | ||||
-rw-r--r-- | g10/plaintext.c | 3 | ||||
-rw-r--r-- | g10/revoke.c | 2 | ||||
-rw-r--r-- | g10/seckey-cert.c | 12 | ||||
-rw-r--r-- | g10/sign.c | 12 |
18 files changed, 756 insertions, 127 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog index 2838c7c8a..c320110c9 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,35 @@ +Tue May 26 11:24:33 1998 Werner Koch (wk@isil.d.shuttle.de) + + * passphrase.c (get_last_passphrase): New + (set_next_passphrase): New. + (passphrase_to_dek): add support for the above functions. + * keyedit.c (make_keysig_packet): Add sigclass 0x18, + changed all callers due to a new argument. + * keygen.c (write_keybinding): New + (generate_subkeypair): Add functionality + (ask_algo, ask_keysize, ask_valid_days): Broke out of generate_keypair + (ask_user_id, ask_passphrase): Ditto. + +Thu May 21 11:26:13 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c,gpgd.c (main): Does now return an int, so that egcs does + not complain. + + * armor.c (fake_packet): Removed erro message and add a noticed + that this part should be fixed. + + * sign.c (sign_file): Compression now comes in front of encryption. + * encode.c (encode_simple): Ditto. + (encode_crypt): Ditto. + +Tue May 19 16:18:19 1998 Werner Koch (wk@isil.d.shuttle.de) + + * armor.c (fake_packet): Changed assertion to log_error + +Sat May 16 16:02:06 1998 Werner Koch (wk@isil.d.shuttle.de) + + * build-packet.c (build_packet): Add SUBKEY packets. + Fri May 15 17:57:23 1998 Werner Koch (wk@isil.d.shuttle.de) * sign.c (hash_for): New and used in all places here. diff --git a/g10/armor.c b/g10/armor.c index 462dc17b3..49352a1eb 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -703,8 +703,13 @@ fake_packet( armor_filter_context_t *afx, IOBUF a, break; case fhdrENDClearsig: - assert( emplines ); - emplines--; /* don't count the last one */ + /* FIXME: this is wrong: Only the last CRLF should + * not be included in the hash, muts rewrite the FSM again + * This proble does only occur if the last line does not end + * in with a LF? + */ + if( emplines ) + emplines--; /* don't count the last one */ state = fhdrENDClearsigHelp; afx->helplen = n; break; diff --git a/g10/build-packet.c b/g10/build-packet.c index 1d4e05871..a37aba55c 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -82,9 +82,11 @@ build_packet( IOBUF out, PACKET *pkt ) case PKT_COMMENT: rc = do_comment( out, ctb, pkt->pkt.comment ); break; + case PKT_PUBKEY_SUBCERT: case PKT_PUBLIC_CERT: rc = do_public_cert( out, ctb, pkt->pkt.public_cert ); break; + case PKT_SECKEY_SUBCERT: case PKT_SECRET_CERT: rc = do_secret_cert( out, ctb, pkt->pkt.secret_cert ); break; diff --git a/g10/compress.c b/g10/compress.c index 4e4d438e0..ca5adaebd 100644 --- a/g10/compress.c +++ b/g10/compress.c @@ -75,6 +75,9 @@ do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, IOBUF a ) do { zs->next_out = zfx->outbuf; zs->avail_out = zfx->outbufsize; + if( DBG_FILTER ) + log_debug("call deflate: avail_in=%u, avail_out=%u\n", + (unsigned)zs->avail_in, (unsigned)zs->avail_out); zrc = deflate( zs, flush ); if( zrc == Z_STREAM_END && flush == Z_FINISH ) ; @@ -145,6 +148,9 @@ do_uncompress( compress_filter_context_t *zfx, z_stream *zs, } zs->avail_in = n; } + if( DBG_FILTER ) + log_debug("call inflate: avail_in=%u, avail_out=%u\n", + (unsigned)zs->avail_in, (unsigned)zs->avail_out); zrc = inflate( zs, Z_PARTIAL_FLUSH ); if( DBG_FILTER ) log_debug("inflate returned: avail_in=%u, avail_out=%u, zrc=%d\n", diff --git a/g10/encode.c b/g10/encode.c index 1e37dfd74..142ffeac2 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -112,13 +112,10 @@ encode_simple( const char *filename, int mode ) if( opt.armor ) iobuf_push_filter( out, armor_filter, &afx ); - - write_comment( out, "#created by GNUPG v" VERSION " (" + else + write_comment( out, "#created by GNUPG v" VERSION " (" PRINTABLE_OS_NAME ")"); - if( opt.compress ) - iobuf_push_filter( out, compress_filter, &zfx ); - if( s2k ) { PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc ); enc->version = 4; @@ -150,11 +147,14 @@ encode_simple( const char *filename, int mode ) pt->buf = inp; pkt.pkttype = PKT_PLAINTEXT; pkt.pkt.plaintext = pt; - cfx.datalen = filesize? calc_packet_length( &pkt ) : 0; + cfx.datalen = filesize && !opt.compress ? calc_packet_length( &pkt ) : 0; /* register the cipher filter */ if( mode ) iobuf_push_filter( out, cipher_filter, &cfx ); + /* register the compress filter */ + if( opt.compress ) + iobuf_push_filter( out, compress_filter, &zfx ); /* do the work */ if( (rc = build_packet( out, &pkt )) ) @@ -211,13 +211,10 @@ encode_crypt( const char *filename, STRLIST remusr ) if( opt.armor ) iobuf_push_filter( out, armor_filter, &afx ); - - write_comment( out, "#created by GNUPG v" VERSION " (" + else + write_comment( out, "#created by GNUPG v" VERSION " (" PRINTABLE_OS_NAME ")"); - if( opt.compress ) - iobuf_push_filter( out, compress_filter, &zfx ); - /* create a session key */ cfx.dek = m_alloc_secure( sizeof *cfx.dek ); cfx.dek->algo = opt.def_cipher_algo; @@ -249,10 +246,13 @@ encode_crypt( const char *filename, STRLIST remusr ) init_packet(&pkt); pkt.pkttype = PKT_PLAINTEXT; pkt.pkt.plaintext = pt; - cfx.datalen = filesize? calc_packet_length( &pkt ) : 0; + cfx.datalen = filesize && !opt.compress? calc_packet_length( &pkt ) : 0; /* register the cipher filter */ iobuf_push_filter( out, cipher_filter, &cfx ); + /* register the compress filter */ + if( opt.compress ) + iobuf_push_filter( out, compress_filter, &zfx ); /* do the work */ if( (rc = build_packet( out, &pkt )) ) @@ -201,7 +201,7 @@ strusage( int level ) case 13: p = VERSION; break; case 17: p = PRINTABLE_OS_NAME; break; case 19: p = - _("Please report bugs to <gnupg-bugs@isil.d.shuttle.de>.\n"); + _("Please report bugs to <gnupg-bugs@gnu.org>.\n"); break; case 1: case 40: p = @@ -364,7 +364,7 @@ check_opts(void) -void +int main( int argc, char **argv ) { ARGPARSE_ARGS pargs; @@ -1005,6 +1005,7 @@ main( int argc, char **argv ) FREE_STRLIST(remusr); FREE_STRLIST(locusr); g10_exit(0); + return 8; /*NEVER REACHED*/ } diff --git a/g10/gpgd.c b/g10/gpgd.c index 010b319b9..72fcade8d 100644 --- a/g10/gpgd.c +++ b/g10/gpgd.c @@ -58,7 +58,7 @@ strusage( int level ) case 13: p = VERSION; break; case 17: p = PRINTABLE_OS_NAME; break; case 19: p = - "Please report bugs to <gnupg-bugs@isil.d.shuttle.de>.\n"; + "Please report bugs to <gnupg-bugs@gnu.org>.\n"; break; case 1: case 40: p = "Usage: gpgd [options] (-h for help)"; @@ -135,7 +135,7 @@ set_debug(void) } -void +int main( int argc, char **argv ) { ARGPARSE_ARGS pargs; @@ -236,9 +236,8 @@ main( int argc, char **argv ) become_daemon(); - - g10_exit(0); + return 8; /*NEVER REACHED*/ } diff --git a/g10/import.c b/g10/import.c index 68ecd5330..228c754eb 100644 --- a/g10/import.c +++ b/g10/import.c @@ -43,7 +43,8 @@ static int chk_self_sigs( const char *fname, KBNODE keyblock, PKT_public_cert *pkc, u32 *keyid ); static int delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid ); static int merge_blocks( const char *fname, KBNODE keyblock_orig, - KBNODE keyblock, u32 *keyid, int *n_uids, int *n_sigs ); + KBNODE keyblock, u32 *keyid, + int *n_uids, int *n_sigs, int *n_subk ); static int append_uid( KBNODE keyblock, KBNODE node, int *n_sigs, const char *fname, u32 *keyid ); static int merge_sigs( KBNODE dst, KBNODE src, int *n_sigs, @@ -103,7 +104,7 @@ import_pubkeys( const char *fname ) return G10ERR_OPEN_FILE; } - if( !opt.no_armor ) /* armored reading is not diabled */ + if( !opt.no_armor ) /* armored reading is not disabled */ iobuf_push_filter( inp, armor_filter, &afx ); while( !(rc = read_block( inp, &cfx, &pending_pkt, &keyblock) )) { @@ -305,7 +306,7 @@ import_one( const char *fname, KBNODE keyblock ) log_info("%s: key %08lX imported\n", fname, (ulong)keyid[1]); } else { /* merge */ - int n_uids, n_sigs; + int n_uids, n_sigs, n_subk; /* Compare the original against the new key; just to be sure nothing * weird is going on */ @@ -335,12 +336,13 @@ import_one( const char *fname, KBNODE keyblock ) /* and try to merge the block */ clear_kbnode_flags( keyblock_orig ); clear_kbnode_flags( keyblock ); - n_uids = n_sigs = 0; + n_uids = n_sigs = n_subk = 0; rc = merge_blocks( fname, keyblock_orig, keyblock, - keyid, &n_uids, &n_sigs ); + keyid, &n_uids, &n_sigs, &n_subk ); if( rc ) goto leave; - if( n_uids || n_sigs ) { /* keyblock_orig has been updated; write */ + if( n_uids || n_sigs || n_subk ) { + /* keyblock_orig has been updated; write */ if( opt.verbose > 1 ) log_info("%s: writing to '%s'\n", fname, keyblock_resource_name(&kbpos) ); @@ -364,6 +366,12 @@ import_one( const char *fname, KBNODE keyblock ) else if( n_sigs ) log_info("%s: key %08lX, %d new signatures\n", fname, (ulong)keyid[1], n_sigs ); + if( n_subk == 1 ) + log_info("%s: key %08lX, 1 new subkey\n", + fname, (ulong)keyid[1]); + else if( n_subk ) + log_info("%s: key %08lX, %d new subkeys\n", + fname, (ulong)keyid[1], n_subk ); } else log_info("%s: key %08lX, not changed\n", fname, (ulong)keyid[1] ); @@ -593,7 +601,7 @@ delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid ) */ static int merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock, - u32 *keyid, int *n_uids, int *n_sigs ) + u32 *keyid, int *n_uids, int *n_sigs, int *n_subk ) { KBNODE onode, node; int rc, found; @@ -667,6 +675,9 @@ merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock, } } + /* 4th: add new subkeys */ + /* FIXME */ + return 0; } diff --git a/g10/keydb.h b/g10/keydb.h index 968ee692a..3df11771e 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -98,6 +98,8 @@ int build_skc_list( STRLIST locusr, SKC_LIST *ret_skc_list, void set_passphrase_fd( int fd ); int get_passphrase_fd(void); DEK *passphrase_to_dek( u32 *keyid, int cipher_algo, STRING2KEY *s2k, int mode); +void set_next_passphrase( const char *s ); +char *get_last_passphrase(void); /*-- getkey.c --*/ void add_keyring( const char *name ); diff --git a/g10/keyedit.c b/g10/keyedit.c index 77da1977b..f5c95ea32 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -169,10 +169,6 @@ remove_keysigs( KBNODE keyblock, u32 *keyid, int all ) && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) { PKT_signature *sig = node->pkt->pkt.signature; - if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) { - /* fixme: skip self-sig */ - } - tty_printf("\n \"%08lX %s ", sig->keyid[1], datestr_from_sig(sig)); if( node->flag & 6 ) @@ -349,6 +345,7 @@ sign_key( const char *username, STRLIST locusr ) rc = make_keysig_packet( &sig, pkc, node->pkt->pkt.user_id, + NULL, skc_rover->skc, 0x10, 0 ); if( rc ) { @@ -568,9 +565,10 @@ change_passphrase( const char *username ) KBNODE node; KBPOS kbpos; PKT_secret_cert *skc; - u32 skc_keyid[2]; + u32 keyid[2]; char *answer; int changed=0; + char *passphrase = NULL; /* find the userid */ rc = find_secret_keyblock_byname( &kbpos, username ); @@ -595,18 +593,28 @@ change_passphrase( const char *username ) } skc = node->pkt->pkt.secret_cert; - keyid_from_skc( skc, skc_keyid ); + keyid_from_skc( skc, keyid ); tty_printf("sec %4u%c/%08lX %s ", nbits_from_skc( skc ), pubkey_letter( skc->pubkey_algo ), - skc_keyid[1], datestr_from_skc(skc) ); + keyid[1], datestr_from_skc(skc) ); { size_t n; - char *p = get_user_id( skc_keyid, &n ); + char *p = get_user_id( keyid, &n ); tty_print_string( p, n ); m_free(p); tty_printf("\n"); } + for(node=keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_SECKEY_SUBCERT ) { + PKT_secret_cert *subskc = node->pkt->pkt.secret_cert; + keyid_from_skc( subskc, keyid ); + tty_printf("sub %4u%c/%08lX %s\n", + nbits_from_skc( subskc ), + pubkey_letter( subskc->pubkey_algo ), + keyid[1], datestr_from_skc(subskc) ); + } + } clear_kbnode_flags( keyblock ); switch( is_secret_key_protected( skc ) ) { @@ -619,10 +627,21 @@ change_passphrase( const char *username ) default: tty_printf("Key is protected.\n"); rc = check_secret_key( skc ); + if( !rc ) + passphrase = get_last_passphrase(); break; } - /* fixme: unprotect all subkeys */ + /* unprotect all subkeys (use the supplied passphrase or ask)*/ + for(node=keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_SECKEY_SUBCERT ) { + PKT_secret_cert *subskc = node->pkt->pkt.secret_cert; + set_next_passphrase( passphrase ); + rc = check_secret_key( subskc ); + if( rc ) + break; + } + } if( rc ) tty_printf("Can't edit this key: %s\n", g10_errstr(rc)); @@ -632,6 +651,7 @@ change_passphrase( const char *username ) tty_printf(_("Enter the new passphrase for this secret key.\n\n") ); + set_next_passphrase( NULL ); for(;;) { s2k->mode = 1; s2k->hash_algo = DIGEST_ALGO_RMD160; @@ -651,10 +671,17 @@ change_passphrase( const char *username ) break; } else { /* okay */ - /* fixme: protect all subkeys too */ skc->protect.algo = dek->algo; skc->protect.s2k = *s2k; rc = protect_secret_key( skc, dek ); + for(node=keyblock; !rc && node; node = node->next ) { + if( node->pkt->pkttype == PKT_SECKEY_SUBCERT ) { + PKT_secret_cert *subskc = node->pkt->pkt.secret_cert; + subskc->protect.algo = dek->algo; + subskc->protect.s2k = *s2k; + rc = protect_secret_key( subskc, dek ); + } + } if( rc ) log_error("protect_secret_key failed: %s\n", g10_errstr(rc) ); else @@ -676,7 +703,9 @@ change_passphrase( const char *username ) } leave: + m_free( passphrase ); release_kbnode( keyblock ); + set_next_passphrase( NULL ); return rc; } @@ -689,14 +718,16 @@ change_passphrase( const char *username ) */ int make_keysig_packet( PKT_signature **ret_sig, PKT_public_cert *pkc, - PKT_user_id *uid, PKT_secret_cert *skc, + PKT_user_id *uid, PKT_public_cert *subpkc, + PKT_secret_cert *skc, int sigclass, int digest_algo ) { PKT_signature *sig; int rc=0; MD_HANDLE md; - assert( (sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x20 ); + assert( (sigclass >= 0x10 && sigclass <= 0x13) + || sigclass == 0x20 || sigclass == 0x18 ); if( !digest_algo ) { switch( skc->pubkey_algo ) { case PUBKEY_ALGO_DSA: digest_algo = DIGEST_ALGO_SHA1; break; @@ -706,11 +737,13 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_cert *pkc, } } md = md_open( digest_algo, 0 ); - /*md_start_debug( md, "make" );*/ /* hash the public key certificate and the user id */ hash_public_cert( md, pkc ); - if( sigclass != 0x20 ) { + if( sigclass == 0x18 ) { /* subkey binding */ + hash_public_cert( md, subpkc ); + } + else if( sigclass != 0x20 ) { if( skc->version >=4 ) { byte buf[5]; buf[0] = 0xb4; /* indicates a userid packet */ @@ -759,7 +792,7 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_cert *pkc, /* add some magic */ buf[0] = sig->version; buf[1] = 0xff; - buf[2] = n >> 24; /* hmmm, n is only 16 bit, so tthis is always 0 */ + buf[2] = n >> 24; /* hmmm, n is only 16 bit, so this is always 0 */ buf[3] = n >> 16; buf[4] = n >> 8; buf[5] = n; diff --git a/g10/keygen.c b/g10/keygen.c index b6894ab79..367c22de5 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -79,7 +79,47 @@ write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_cert *skc ) pkc = node->pkt->pkt.public_cert; /* and make the signature */ - rc = make_keysig_packet( &sig, pkc, uid, skc, 0x13, 0 ); + rc = make_keysig_packet( &sig, pkc, uid, NULL, skc, 0x13, 0 ); + if( rc ) { + log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) ); + return rc; + } + + pkt = m_alloc_clear( sizeof *pkt ); + pkt->pkttype = PKT_SIGNATURE; + pkt->pkt.signature = sig; + add_kbnode( root, new_kbnode( pkt ) ); + return rc; +} + +static int +write_keybinding( KBNODE root, KBNODE pub_root, PKT_secret_cert *skc ) +{ + PACKET *pkt; + PKT_signature *sig; + int rc=0; + KBNODE node; + PKT_public_cert *pkc, *subpkc; + + if( opt.verbose ) + log_info(_("writing key binding signature\n")); + + /* get the pkc packet from the pub_tree */ + node = find_kbnode( pub_root, PKT_PUBLIC_CERT ); + if( !node ) + BUG(); + pkc = node->pkt->pkt.public_cert; + /* find the last subkey */ + subpkc = NULL; + for(node=pub_root; node; node = node->next ) { + if( node->pkt->pkttype == PKT_PUBKEY_SUBCERT ) + subpkc = node->pkt->pkt.public_cert; + } + if( !subpkc ) + BUG(); + + /* and make the signature */ + rc = make_keysig_packet( &sig, pkc, NULL, subpkc, skc, 0x18, 0 ); if( rc ) { log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) ); return rc; @@ -95,7 +135,8 @@ write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_cert *skc ) static int gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, - STRING2KEY *s2k, PKT_secret_cert **ret_skc, u16 valid_days ) + STRING2KEY *s2k, PKT_secret_cert **ret_skc, u16 valid_days, + int version ) { int rc; int i; @@ -111,6 +152,7 @@ gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, skc = m_alloc_clear( sizeof *skc ); pkc = m_alloc_clear( sizeof *pkc ); skc->timestamp = pkc->timestamp = make_timestamp(); + skc->version = pkc->version = version; skc->valid_days = pkc->valid_days = valid_days; skc->pubkey_algo = pkc->pubkey_algo = PUBKEY_ALGO_ELGAMAL; pkc->d.elg.p = pk.p; @@ -124,8 +166,8 @@ gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, skc->protect.algo = 0; skc->csum = checksum_mpi( skc->d.elg.x ); - /* return an unprotected version of the skc */ - *ret_skc = copy_secret_cert( NULL, skc ); + if( ret_skc ) /* not a subkey: return an unprotected version of the skc */ + *ret_skc = copy_secret_cert( NULL, skc ); if( dek ) { skc->protect.algo = dek->algo; @@ -140,14 +182,14 @@ gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, } pkt = m_alloc_clear(sizeof *pkt); - pkt->pkttype = PKT_PUBLIC_CERT; + pkt->pkttype = ret_skc ? PKT_PUBLIC_CERT : PKT_PUBKEY_SUBCERT; pkt->pkt.public_cert = pkc; add_kbnode(pub_root, new_kbnode( pkt )); /* don't know whether it makes sense to have the factors, so for now * we store them in the secret keyring (but they are not secret) */ pkt = m_alloc_clear(sizeof *pkt); - pkt->pkttype = PKT_SECRET_CERT; + pkt->pkttype = ret_skc ? PKT_SECRET_CERT : PKT_SECKEY_SUBCERT; pkt->pkt.secret_cert = skc; add_kbnode(sec_root, new_kbnode( pkt )); for(i=0; factors[i]; i++ ) @@ -192,8 +234,8 @@ gen_rsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, skc->d.rsa.csum += checksum_mpi( skc->d.rsa.rsa_q ); skc->d.rsa.csum += checksum_mpi( skc->d.rsa.rsa_u ); - /* return an unprotected version of the skc */ - *ret_skc = copy_secret_cert( NULL, skc ); + if( ret_skc ) /* not a subkey: return an unprotected version of the skc */ + *ret_skc = copy_secret_cert( NULL, skc ); if( dek ) { skc->d.rsa.is_protected = 1; @@ -210,12 +252,12 @@ gen_rsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, } pkt = m_alloc_clear(sizeof *pkt); - pkt->pkttype = PKT_PUBLIC_CERT; + pkt->pkttype = ret_skc ? PKT_PUBLIC_CERT : PKT_PUBKEY_SUBCERT; pkt->pkt.public_cert = pkc; add_kbnode(pub_root, new_kbnode( pkt )); pkt = m_alloc_clear(sizeof *pkt); - pkt->pkttype = PKT_SECRET_CERT; + pkt->pkttype = ret_skc ? PKT_SECRET_CERT : PKT_SECKEY_SUBCERT; pkt->pkt.secret_cert = skc; add_kbnode(sec_root, new_kbnode( pkt )); @@ -267,8 +309,8 @@ gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, skc->protect.algo = 0; skc->csum = checksum_mpi( skc->d.dsa.x ); - /* return an unprotected version of the skc */ - *ret_skc = copy_secret_cert( NULL, skc ); + if( ret_skc ) /* not a subkey: return an unprotected version of the skc */ + *ret_skc = copy_secret_cert( NULL, skc ); if( dek ) { skc->protect.algo = dek->algo; @@ -283,7 +325,7 @@ gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, } pkt = m_alloc_clear(sizeof *pkt); - pkt->pkttype = PKT_PUBLIC_CERT; + pkt->pkttype = ret_skc ? PKT_PUBLIC_CERT : PKT_PUBKEY_SUBCERT; pkt->pkt.public_cert = pkc; add_kbnode(pub_root, new_kbnode( pkt )); @@ -294,7 +336,7 @@ gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, * are known. */ pkt = m_alloc_clear(sizeof *pkt); - pkt->pkttype = PKT_SECRET_CERT; + pkt->pkttype = ret_skc ? PKT_SECRET_CERT : PKT_SECKEY_SUBCERT; pkt->pkt.secret_cert = skc; add_kbnode(sec_root, new_kbnode( pkt )); for(i=1; factors[i]; i++ ) /* the first one is q */ @@ -334,74 +376,63 @@ check_valid_days( const char *s ) } -/**************** - * Generate a keypair - */ -void -generate_keypair() +static int +ask_algo( int *ret_v4 ) { char *answer; - unsigned nbits; - char *pub_fname = NULL; - char *sec_fname = NULL; - char *uid = NULL; - KBNODE pub_root = NULL; - KBNODE sec_root = NULL; - PKT_secret_cert *skc = NULL; - DEK *dek = NULL; - STRING2KEY *s2k; - int rc; int algo; - const char *algo_name; - char *aname, *acomment, *amail; - int valid_days=0; - - if( opt.batch || opt.answer_yes || opt.answer_no ) { - log_error(_("Key generation can only be used in interactive mode\n")); - return; - } tty_printf(_("Please select the algorithm to use:\n" " (1) ElGamal is the suggested one.\n" - " (2) DSA can only be used for signatures.\n")); + " (2) ElGamal using v4 packets (OpenPGP)\n" + " (3) DSA can only be used for signatures.\n")); #ifdef ENABLE_RSA_KEYGEN - tty_printf(_(" (3) RSA cannot be used in the U.S.\n")); + tty_printf(_(" (4) RSA cannot be used in the U.S.\n")); #endif + *ret_v4 = 0; for(;;) { #ifdef ENABLE_RSA_KEYGEN - answer = tty_get(_("Your selection? (1,2,3) ")); + answer = tty_get(_("Your selection? (1,2,3,4) ")); #else - answer = tty_get(_("Your selection? (1,2) ")); + answer = tty_get(_("Your selection? (1,2,3) ")); #endif tty_kill_prompt(); algo = *answer? atoi(answer): 1; m_free(answer); - if( algo == 1 ) { + if( algo == 1 || algo == 2 ) { + if( algo == 2 ) + *ret_v4 = 1; algo = PUBKEY_ALGO_ELGAMAL; - algo_name = "ElGamal"; break; } - else if( algo == 2 ) { + else if( algo == 3 ) { + *ret_v4 = 1; algo = PUBKEY_ALGO_DSA; - algo_name = "DSA"; break; } #ifdef ENABLE_RSA_KEYGEN - else if( algo == 3 ) { + else if( algo == 4 ) { algo = PUBKEY_ALGO_RSA; - algo_name = "RSA"; break; } #endif } + return algo; +} +static unsigned +ask_keysize( int algo ) +{ + char *answer; + unsigned nbits; tty_printf(_("About to generate a new %s keypair.\n" " minimum keysize is 768 bits\n" " default keysize is 1024 bits\n" - " highest suggested keysize is 2048 bits\n"), algo_name ); + " highest suggested keysize is 2048 bits\n"), + pubkey_algo_to_string(algo) ); for(;;) { answer = tty_get(_("What keysize do you want? (1024) ")); tty_kill_prompt(); @@ -446,6 +477,15 @@ generate_keypair() nbits = ((nbits + 31) / 32) * 32; tty_printf(_("rounded up to %u bits\n"), nbits ); } + return nbits; +} + + +static int +ask_valid_days() +{ + char *answer; + int valid_days=0; tty_printf(_("Please specify how long the key should be valid.\n" " 0 = key does not expire\n" @@ -491,15 +531,21 @@ generate_keypair() break; } m_free(answer); + return valid_days; +} +static char * +ask_user_id() +{ + char *answer; + char *aname, *acomment, *amail, *uid; tty_printf( _("\n" "You need a User-ID to identify your key; the software constructs the user id\n" "from Real Name, Comment and Email Address in this form:\n" " \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n\n") ); - uid = NULL; - aname=acomment=amail=NULL; + uid = aname = acomment = amail = NULL; for(;;) { char *p; @@ -600,7 +646,15 @@ generate_keypair() break; m_free(uid); uid = NULL; } + return uid; +} + +static DEK * +ask_passphrase( STRING2KEY **ret_s2k ) +{ + DEK *dek = NULL; + STRING2KEY *s2k; tty_printf(_("You need a Passphrase to protect your secret key.\n\n") ); @@ -624,23 +678,17 @@ generate_keypair() else break; /* okay */ } + *ret_s2k = s2k; + return dek; +} - /* now check whether we are allowed to write to the keyrings */ - pub_fname = make_filename(opt.homedir, "pubring.gpg", NULL ); - sec_fname = make_filename(opt.homedir, "secring.gpg", NULL ); - if( opt.verbose ) { - tty_printf(_("writing public certificate to '%s'\n"), pub_fname ); - tty_printf(_("writing secret certificate to '%s'\n"), sec_fname ); - } - - /* we create the packets as a tree of kbnodes. Because the structure - * we create is known in advance we simply generate a linked list - * The first packet is a dummy comment packet which we flag - * as deleted. The very first packet must always be a CERT packet. - */ - pub_root = make_comment_node("#"); delete_kbnode(pub_root); - sec_root = make_comment_node("#"); delete_kbnode(sec_root); +static int +do_create( int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, + DEK *dek, STRING2KEY *s2k, PKT_secret_cert **skc, int valid_days, + int v4_packet ) +{ + int rc=0; tty_printf(_( "We need to generate a lot of random bytes. It is a good idea to perform\n" @@ -649,13 +697,14 @@ generate_keypair() "number generator a better chance to gain enough entropy.\n") ); if( algo == PUBKEY_ALGO_ELGAMAL ) - rc = gen_elg(nbits, pub_root, sec_root, dek, s2k, &skc, valid_days ); + rc = gen_elg(nbits, pub_root, sec_root, dek, s2k, + skc, valid_days, v4_packet? 4:3 ); #ifdef ENABLE_RSA_KEYGEN else if( algo == PUBKEY_ALGO_RSA ) - rc = gen_rsa(nbits, pub_root, sec_root, dek, s2k, &skc, valid_days ); + rc = gen_rsa(nbits, pub_root, sec_root, dek, s2k, skc, valid_days ); #endif else if( algo == PUBKEY_ALGO_DSA ) - rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, &skc, valid_days); + rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, skc, valid_days); else BUG(); if( !rc ) { @@ -666,6 +715,59 @@ generate_keypair() make_comment_node("#created by GNUPG v" VERSION " (" PRINTABLE_OS_NAME ")")); } + return rc; +} + + +/**************** + * Generate a keypair + */ +void +generate_keypair() +{ + unsigned nbits; + char *pub_fname = NULL; + char *sec_fname = NULL; + char *uid = NULL; + KBNODE pub_root = NULL; + KBNODE sec_root = NULL; + PKT_secret_cert *skc = NULL; + DEK *dek; + STRING2KEY *s2k; + int rc; + int algo; + int ndays; + int v4; + + if( opt.batch || opt.answer_yes || opt.answer_no ) { + log_error(_("Key generation can only be used in interactive mode\n")); + return; + } + + algo = ask_algo( &v4 ); + nbits = ask_keysize( algo ); + ndays = ask_valid_days(); + uid = ask_user_id(); + dek = ask_passphrase( &s2k ); + + + /* now check whether we are allowed to write to the keyrings */ + pub_fname = make_filename(opt.homedir, "pubring.gpg", NULL ); + sec_fname = make_filename(opt.homedir, "secring.gpg", NULL ); + if( opt.verbose ) { + tty_printf(_("writing public certificate to '%s'\n"), pub_fname ); + tty_printf(_("writing secret certificate to '%s'\n"), sec_fname ); + } + + /* we create the packets as a tree of kbnodes. Because the structure + * we create is known in advance we simply generate a linked list + * The first packet is a dummy comment packet which we flag + * as deleted. The very first packet must always be a CERT packet. + */ + pub_root = make_comment_node("#"); delete_kbnode(pub_root); + sec_root = make_comment_node("#"); delete_kbnode(sec_root); + + rc = do_create( algo, nbits, pub_root, sec_root, dek, s2k, &skc, ndays, v4); if( !rc ) write_uid(pub_root, uid ); if( !rc ) @@ -718,6 +820,11 @@ generate_keypair() log_error("can't write secret key: %s\n", g10_errstr(rc) ); else { tty_printf(_("public and secret key created and signed.\n") ); + if( algo == PUBKEY_ALGO_DSA ) + tty_printf(_("Note that this key cannot be used for " + "encryption. You may want to use\n" + "the command \"--add-key\" to generate a " + "secondary key for this purpose.\n") ); } if( !rc1 ) @@ -745,8 +852,148 @@ generate_keypair() * add a new subkey to an existing key. */ void -generate_subkeypair( const char *userid ) +generate_subkeypair( const char *username ) { - log_fatal("To be implemented :-)\n"); + int rc=0; + KBPOS pub_kbpos, sec_kbpos; + KBNODE pub_keyblock = NULL; + KBNODE sec_keyblock = NULL; + KBNODE node; + PKT_secret_cert *skc = NULL; /* this is the primary skc */ + u32 keyid[2]; + int v4, algo, ndays; + unsigned nbits; + char *passphrase = NULL; + DEK *dek = NULL; + STRING2KEY *s2k = NULL; + + if( opt.batch || opt.answer_yes || opt.answer_no ) { + log_error(_("Key generation can only be used in interactive mode\n")); + return; + } + + /* search the userid */ + rc = find_secret_keyblock_byname( &sec_kbpos, username ); + if( rc ) { + log_error("user '%s' not found\n", username ); + goto leave; + } + rc = read_keyblock( &sec_kbpos, &sec_keyblock ); + if( rc ) { + log_error("error reading the secret key: %s\n", g10_errstr(rc) ); + goto leave; + } + /* and the public key */ + rc = find_keyblock_byname( &pub_kbpos, username ); + if( rc ) { + log_error("user '%s' not found in public ring\n", username ); + goto leave; + } + rc = read_keyblock( &pub_kbpos, &pub_keyblock ); + if( rc ) { + log_error("error reading the public key: %s\n", g10_errstr(rc) ); + goto leave; + } + + /* break out the primary key */ + node = find_kbnode( sec_keyblock, PKT_SECRET_CERT ); + if( !node ) { + log_error("Oops; secret key not found anymore!\n"); + rc = G10ERR_GENERAL; + goto leave; + } + + /* make a copy of the skc to keep the protected one in the keyblock */ + skc = copy_secret_cert( NULL, node->pkt->pkt.secret_cert ); + keyid_from_skc( skc, keyid ); + /* display primary and all secondary keys */ + tty_printf("sec %4u%c/%08lX %s ", + nbits_from_skc( skc ), + pubkey_letter( skc->pubkey_algo ), + keyid[1], datestr_from_skc(skc) ); + { + size_t n; + char *p = get_user_id( keyid, &n ); + tty_print_string( p, n ); + m_free(p); + tty_printf("\n"); + } + for(node=sec_keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_SECKEY_SUBCERT ) { + PKT_secret_cert *subskc = node->pkt->pkt.secret_cert; + keyid_from_skc( subskc, keyid ); + tty_printf("sub %4u%c/%08lX %s\n", + nbits_from_skc( subskc ), + pubkey_letter( subskc->pubkey_algo ), + keyid[1], datestr_from_skc(subskc) ); + } + } + tty_printf("\n"); + + + + /* unprotect to get the passphrase */ + switch( is_secret_key_protected( skc ) ) { + case -1: + rc = G10ERR_PUBKEY_ALGO; + break; + case 0: + tty_printf("This key is not protected.\n"); + break; + default: + tty_printf("Key is protected.\n"); + rc = check_secret_key( skc ); + if( !rc ) + passphrase = get_last_passphrase(); + break; + } + if( rc ) + goto leave; + + + algo = ask_algo( &v4 ); + nbits = ask_keysize( algo ); + ndays = ask_valid_days(); + + if( passphrase ) { + s2k = m_alloc_secure( sizeof *s2k ); + s2k->mode = 1; + s2k->hash_algo = DIGEST_ALGO_RMD160; + set_next_passphrase( passphrase ); + dek = passphrase_to_dek( NULL, CIPHER_ALGO_BLOWFISH, s2k, 2 ); + } + + rc = do_create( algo, nbits, pub_keyblock, sec_keyblock, + dek, s2k, NULL, ndays, v4 ); + if( !rc ) + rc = write_keybinding(pub_keyblock, pub_keyblock, skc); + if( !rc ) + rc = write_keybinding(sec_keyblock, pub_keyblock, skc); + /* write back */ + if( !rc ) { + rc = update_keyblock( &pub_kbpos, pub_keyblock ); + if( rc ) + log_error("update_public_keyblock failed\n" ); + } + if( !rc ) { + rc = update_keyblock( &sec_kbpos, sec_keyblock ); + if( rc ) + log_error("update_secret_keyblock failed\n" ); + } + if( !rc ) + tty_printf(_("public and secret subkey created.\n") ); + + + leave: + if( rc ) + tty_printf(_("Key generation failed: %s\n"), g10_errstr(rc) ); + m_free( passphrase ); + m_free( dek ); + m_free( s2k ); + if( skc ) /* release the copy of the (now unprotected) secret key */ + free_secret_cert(skc); + release_kbnode( sec_keyblock ); + release_kbnode( pub_keyblock ); + set_next_passphrase( NULL ); } diff --git a/g10/ks-proto.c b/g10/ks-proto.c index 38f21762b..b862357fb 100644 --- a/g10/ks-proto.c +++ b/g10/ks-proto.c @@ -18,6 +18,32 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ +/**************** + * The extended HKP protocol: + * + * GET /pks/lookup[/<gnupg_user_id>][?[op=<cmd>][&armor=0][&search=<keywords>]] + * + * Default is: "armor=1", "op=get". "search" is only allowed if gnupg_user_id + * is not present. GET maybe replaced by HEAD in which case only some status + * information is returned. + * + * Hmmm, I don't like it, the better solution is to use: + * + * /pks/gnupg/get for binary lookups + * /pks/gnupg/upd to update a key + * /pks/gnupg/ins to insert a new key + * + * Optional a version string can be inserted as in: + * + * /pks/gnupg/v1.0/get + * + * Returned HTTP options: + * X-Key-Hash: <rmd160 hash value of the keyblock> + * X-Key-MTime: <last modification time> + * X-Key-LID: <local_key_id_used_for_update_etc> + * [fixme: is X-.... allowed?] + */ + #include <config.h> #include <stdio.h> #include <stdlib.h> @@ -34,6 +60,226 @@ read_line( FILE *fp ) { return -1; } + + + + +/**************** + * Send a HKP request + */ +int +hkp_request( int operation, const char *user_id ) +{ + +} + + + + + +/************************************************ + ******* client communication stuff ************ + ************************************************/ + +/**************** + * Initialisieren des clients + * Es wird ein Handle zurückgegeben oder -1 bei einem fehler. + * z.Z. ist nut eine Verbindung gleichzeitig möglich. + * Wenn einer serverpid von 0 angegeben wird, so wird diese + * der environment variabeln ATEXDB_PID entnommen. + */ + +int +hkp_open( const char *serverurl ) +{ + const char *s; + + s = SERVER_NAME_TEMPLATE; + client.serv_name = xmalloc(strlen(s) + 10 ); + sprintf(client.serv_name,s, serverpid ); + if( opt.verbose ) + Info("Using unix domain stream '%s'", client.serv_name ); + + memset( &client.serv_addr, 0, sizeof client.serv_addr ); + client.serv_addr.sun_family = AF_UNIX; + strcpy( client.serv_addr.sun_path, client.serv_name ); + client.serv_addr_len = strlen(client.serv_addr.sun_path) + + sizeof client.serv_addr.sun_family; + + client.sockfd = -1; + if( DoCheckVersion() ) + return -1; + return 0; +} + + +static int +DoConnect() +{ + if( client.sockfd != -1 ) + DoDisconnect(); + if( (client.sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 ) { + Error(1000,"can't open unix domain socket"); + return 1; + } + if( connect(client.sockfd, (struct sockaddr*)&client.serv_addr, + client.serv_addr_len) == -1 ) { + Error(1000,"can't connect to '%s'",client.serv_addr.sun_path); + return 1; + } + + return 0; /* okay */ +} + +static int +DoDisconnect() +{ + if( client.sockfd != -1 ) { + close(client.sockfd); + client.sockfd = -1; + } + return 0; /* okay */ +} + +/**************** + * NBYTES auf den aktuellen stream schreiben. + */ +static int +DoWrite( void *buf, size_t nbytes ) +{ + size_t nleft = nbytes; + ssize_t nwritten; + + while( nleft > 0 ) { + /* FIXME: add EINTR handling */ + nwritten = write(client.sockfd, buf, nleft); + if( nwritten < 0 ) { + Error(1000,"error writing to server"); + return -1; + } + nleft -= nwritten; + buf = (char*)buf + nwritten; + } + return 0; +} + +static int +DoWriteStr( const char *s ) +{ + return DoWrite((char *)s, strlen(s) ); +} + + +static int +DoRead( void *buf, size_t buflen, size_t *ret_nread, int stop) +{ + size_t nleft = buflen; + int nread; + char *p; + + p = buf; + while( nleft > 0 ) { + /* FIXME: add EINTR handling */ + nread = read(client.sockfd, buf, stop? 1 : nleft); + if( nread < 0 ) { + Error(1000,"error reading from server"); + return -1; + } + else if( !nread ) + break; /* EOF */ + nleft -= nread; + buf = (char*)buf + nread; + if( stop ) + for(; p < (char*)buf ; p++ ) + if( *p == '\n' ) + goto leave; + } + leave: + if( ret_nread ) + *ret_nread = buflen - nleft; + return 0; +} + +/**************** + * Like DoRead(), but append the received data to the given strgbuf. + * read a maximum of nbytes; + */ +static int +DoReadIntoStrgbuf( strgbuf_t *strgbuf, size_t nbytes, size_t *ret_nread) +{ + size_t ntotal, nleft; + int nread; + byte *p, buffer[1000]; + + ntotal = 0; + nleft = nbytes; + while( nleft ) { + nread = read(client.sockfd, buffer, + nleft > DIM(buffer)? DIM(buffer) : nleft); + if( nread < 0 ) { + Error(1000,"error reading from server"); + return -1; + } + else if( !nread ) + break; /* EOF */ + nleft -= nread; + ntotal += nread; + /* ab in den stringbuffer */ + for(p=buffer; nread; nread--, p++ ) + PutStrgbuf(strgbuf, *p ); + } + + if( ret_nread ) + *ret_nread = ntotal; + return 0; +} + + +/**************** + * In retval wird das numerische argument nach OK zurückgegeben + */ +static int +DoRequest( char *request, long *retval ) +{ + if( DoWrite(request, strlen(request)) ) + return -1; + return DoWaitReply( retval ); +} + +static int +DoWaitReply( long *retval ) +{ + char *p, buf[200]; /* enough room for messages */ + size_t nread; + + /* read but stop at the first newline */ + if( DoRead(buf, DIM(buf)-2, &nread, 1 ) ) + return -1; + buf[DIM(buf)-1] = 0; + /* fixme: should check, that we have the linefeed and otherwise + * perform a dummy read */ + if( p = strchr(buf, '\n') ) + *p = 0; + if( *buf == 'O' && buf[1] == 'K' && (buf[2]==' ' || !buf[2]) ) { + if( retval ) + *retval = buf[2]? strtol(buf+3, NULL, 10 ):0; + return 0; + } + Error(0, "Server replied: %.60s", buf ); + return -1; +} + + + + + + + + + + + + #endif diff --git a/g10/packet.h b/g10/packet.h index 463cf53f2..7f38cd5cf 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -308,7 +308,8 @@ 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, + PKT_user_id *uid, PKT_public_cert *subpkc, + PKT_secret_cert *skc, int sigclass, int digest_algo ); #endif /*G10_PACKET_H*/ diff --git a/g10/passphrase.c b/g10/passphrase.c index d3b882fa8..ebcba9942 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -33,6 +33,8 @@ #include "main.h" static int pwfd = -1; +static char *next_pw = NULL; +static char *last_pw = NULL; static void hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create ); @@ -48,6 +50,34 @@ get_passphrase_fd() return pwfd; } +/**************** + * Set the passphrase to be used for the next query and only for the next + * one. + */ +void +set_next_passphrase( const char *s ) +{ + m_free(next_pw); + next_pw = NULL; + if( s ) { + next_pw = m_alloc_secure( strlen(s)+1 ); + strcpy(next_pw, s ); + } +} + +/**************** + * Get the last passphrase used in passphrase_to_dek. + * Note: This removes the passphrase from this modules and + * the caller must free the result. May return NULL: + */ +char * +get_last_passphrase() +{ + char *p = last_pw; + last_pw = NULL; + return p; +} + /**************** * Get a passphrase for the secret key with KEYID, display TEXT @@ -62,7 +92,7 @@ get_passphrase_fd() DEK * passphrase_to_dek( u32 *keyid, int cipher_algo, STRING2KEY *s2k, int mode ) { - char *pw; + char *pw = NULL; DEK *dek; STRING2KEY help_s2k; @@ -77,7 +107,7 @@ passphrase_to_dek( u32 *keyid, int cipher_algo, STRING2KEY *s2k, int mode ) :DEFAULT_DIGEST_ALGO; } - if( keyid && !opt.batch ) { + if( keyid && !opt.batch && !next_pw ) { char *ustr; tty_printf("Need a pass phrase to unlock the secret key for:\n"); tty_printf(" \"" ); @@ -87,7 +117,11 @@ passphrase_to_dek( u32 *keyid, int cipher_algo, STRING2KEY *s2k, int mode ) tty_printf("\"\n\n"); } - if( pwfd != -1 ) { /* read the passphrase from the given descriptor */ + if( next_pw ) { + pw = next_pw; + next_pw = NULL; + } + else if( pwfd != -1 ) { /* read the passphrase from the file */ int i, len; if( !opt.batch ) @@ -130,7 +164,8 @@ passphrase_to_dek( u32 *keyid, int cipher_algo, STRING2KEY *s2k, int mode ) dek->keylen = 0; else hash_passphrase( dek, pw, s2k, mode==2 ); - m_free(pw); /* is allocated in secure memory, so it will be burned */ + m_free(last_pw); + last_pw = pw; return dek; } diff --git a/g10/plaintext.c b/g10/plaintext.c index e15a269e8..cdf4fe2a2 100644 --- a/g10/plaintext.c +++ b/g10/plaintext.c @@ -77,7 +77,8 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx ) if( pt->len ) { for( ; pt->len; pt->len-- ) { if( (c = iobuf_get(pt->buf)) == -1 ) { - log_error("Problem reading source\n"); + log_error("Problem reading source (%u bytes remaining)\n", + (unsigned)pt->len); rc = G10ERR_READ_FILE; goto leave; } diff --git a/g10/revoke.c b/g10/revoke.c index 68f51e810..cafe84de3 100644 --- a/g10/revoke.c +++ b/g10/revoke.c @@ -159,7 +159,7 @@ gen_revoke( const char *uname ) /* create it */ - rc = make_keysig_packet( &sig, pkc, NULL, skc, 0x20, 0); + rc = make_keysig_packet( &sig, pkc, NULL, NULL, skc, 0x20, 0); if( rc ) { log_error("make_keysig_packet failed: %s\n", g10_errstr(rc)); goto leave; diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index a265a3713..8a5d98299 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -55,7 +55,7 @@ do_check( PKT_secret_cert *cert ) case CIPHER_ALGO_CAST: keyid_from_skc( cert, keyid ); dek = passphrase_to_dek( keyid, cert->protect.algo, - &cert->protect.s2k, 0 ); + &cert->protect.s2k, 0 ); cipher_hd = cipher_open( cert->protect.algo, CIPHER_MODE_AUTO_CFB, 1); cipher_setkey( cipher_hd, dek->key, dek->keylen ); @@ -227,7 +227,7 @@ check_secret_key( PKT_secret_cert *cert ) case PUBKEY_ALGO_ELGAMAL: case PUBKEY_ALGO_DSA: rc = do_check( cert ); - #if 1 /* set to 0 to disable the workaround */ + #if 0 /* set to 1 to enable the workaround */ if( rc == G10ERR_BAD_PASS && cert->is_protected && cert->protect.algo == CIPHER_ALGO_BLOWFISH && cert->pubkey_algo != PUBKEY_ALGO_ELGAMAL ) { @@ -243,11 +243,19 @@ check_secret_key( PKT_secret_cert *cert ) } #endif break; + #ifdef HAVE_RSA_CIPHER + case PUBKEY_ALGO_RSA: + case PUBKEY_ALGO_RSA_E: + case PUBKEY_ALGO_RSA_S: + rc = do_check( cert ); + break; + #endif default: rc = G10ERR_PUBKEY_ALGO; } if( get_passphrase_fd() != -1 ) break; } + return rc; } diff --git a/g10/sign.c b/g10/sign.c index 104aedb42..598f60998 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -170,17 +170,19 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, if( opt.armor && !outfile ) iobuf_push_filter( out, armor_filter, &afx ); - write_comment( out, "#created by GNUPG v" VERSION " (" + else + write_comment( out, "#created by GNUPG v" VERSION " (" PRINTABLE_OS_NAME ")"); - if( opt.compress && !outfile ) - iobuf_push_filter( out, compress_filter, &zfx ); - if( encrypt ) { efx.pkc_list = pkc_list; /* fixme: set efx.cfx.datalen if known */ iobuf_push_filter( out, encrypt_filter, &efx ); } + if( opt.compress && !outfile ) + iobuf_push_filter( out, compress_filter, &zfx ); + + if( !detached ) { /* loop over the secret certificates and build headers */ for( skc_rover = skc_list; skc_rover; skc_rover = skc_rover->next ) { @@ -410,7 +412,6 @@ int clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) { armor_filter_context_t afx; - compress_filter_context_t zfx; text_filter_context_t tfx; MD_HANDLE textmd = NULL; IOBUF inp = NULL, out = NULL; @@ -420,7 +421,6 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) SKC_LIST skc_rover = NULL; memset( &afx, 0, sizeof afx); - memset( &zfx, 0, sizeof zfx); memset( &tfx, 0, sizeof tfx); init_packet( &pkt ); |