mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-02 22:46:30 +02:00
add-key works
This commit is contained in:
parent
f9a7043782
commit
eed2faab53
69 changed files with 2342 additions and 821 deletions
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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",
|
||||
|
|
24
g10/encode.c
24
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*/
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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*/
|
||||
}
|
||||
|
||||
|
||||
|
|
25
g10/import.c
25
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
|
|
399
g10/keygen.c
399
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,8 +646,16 @@ 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") );
|
||||
|
||||
s2k = m_alloc_secure( sizeof *s2k );
|
||||
|
@ -624,6 +678,77 @@ generate_keypair()
|
|||
else
|
||||
break; /* okay */
|
||||
}
|
||||
*ret_s2k = s2k;
|
||||
return dek;
|
||||
}
|
||||
|
||||
|
||||
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"
|
||||
"some other action (work in another window, move the mouse, utilize the\n"
|
||||
"network and the disks) during the prime generation; this gives the random\n"
|
||||
"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, 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 );
|
||||
#endif
|
||||
else if( algo == PUBKEY_ALGO_DSA )
|
||||
rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, skc, valid_days);
|
||||
else
|
||||
BUG();
|
||||
if( !rc ) {
|
||||
add_kbnode( pub_root,
|
||||
make_comment_node("#created by GNUPG v" VERSION " ("
|
||||
PRINTABLE_OS_NAME ")"));
|
||||
add_kbnode( sec_root,
|
||||
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 */
|
||||
|
@ -642,30 +767,7 @@ generate_keypair()
|
|||
pub_root = make_comment_node("#"); delete_kbnode(pub_root);
|
||||
sec_root = make_comment_node("#"); delete_kbnode(sec_root);
|
||||
|
||||
tty_printf(_(
|
||||
"We need to generate a lot of random bytes. It is a good idea to perform\n"
|
||||
"some other action (work in another window, move the mouse, utilize the\n"
|
||||
"network and the disks) during the prime generation; this gives the random\n"
|
||||
"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 );
|
||||
#ifdef ENABLE_RSA_KEYGEN
|
||||
else if( algo == PUBKEY_ALGO_RSA )
|
||||
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);
|
||||
else
|
||||
BUG();
|
||||
if( !rc ) {
|
||||
add_kbnode( pub_root,
|
||||
make_comment_node("#created by GNUPG v" VERSION " ("
|
||||
PRINTABLE_OS_NAME ")"));
|
||||
add_kbnode( sec_root,
|
||||
make_comment_node("#created by GNUPG v" VERSION " ("
|
||||
PRINTABLE_OS_NAME ")"));
|
||||
}
|
||||
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 );
|
||||
}
|
||||
|
||||
|
|
246
g10/ks-proto.c
246
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
|
||||
|
||||
|
||||
|
|
|
@ -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*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
12
g10/sign.c
12
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 );
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue