diff options
Diffstat (limited to 'g10')
-rw-r--r-- | g10/ChangeLog | 27 | ||||
-rw-r--r-- | g10/Makefile.in | 1 | ||||
-rw-r--r-- | g10/encode.c | 2 | ||||
-rw-r--r-- | g10/export.c | 100 | ||||
-rw-r--r-- | g10/g10.c | 232 | ||||
-rw-r--r-- | g10/import.c | 35 | ||||
-rw-r--r-- | g10/kbnode.c | 9 | ||||
-rw-r--r-- | g10/keydb.h | 3 | ||||
-rw-r--r-- | g10/keygen.c | 14 | ||||
-rw-r--r-- | g10/parse-packet.c | 2 | ||||
-rw-r--r-- | g10/pubkey-enc.c | 68 | ||||
-rw-r--r-- | g10/ringedit.c | 141 | ||||
-rw-r--r-- | g10/sign.c | 4 |
13 files changed, 483 insertions, 155 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog new file mode 100644 index 000000000..2bfa48b74 --- /dev/null +++ b/g10/ChangeLog @@ -0,0 +1,27 @@ +Fri Feb 13 20:18:14 1998 Werner Koch ([email protected]) + + * ringedit.c (enum_keyblocks, keyring_enum): New. + +Fri Feb 13 19:33:40 1998 Werner Koch ([email protected]) + + * export.c: Add functionality. + + * keygen.c (generate_keypair): Moved the leading comment behind the + key packet. + * kbnode.c (walk_kbnode): Fixed. + + * g10.c (main): listing armored keys now work. + +Fri Feb 13 16:17:43 1998 Werner Koch ([email protected]) + + * parse-packet.c (parse_publickey, parse_signature): Fixed calls + to mpi_read used for ELG b. + +Fri Feb 13 15:13:23 1998 Werner Koch ([email protected]) + + * g10.c (main): changed formatting of help output. + +Thu Feb 12 22:24:42 1998 Werner Koch (wk@frodo) + + * pubkey-enc.c (get_session_key): rewritten + diff --git a/g10/Makefile.in b/g10/Makefile.in index 63ffc3e6b..afbeebf8f 100644 --- a/g10/Makefile.in +++ b/g10/Makefile.in @@ -85,7 +85,6 @@ POSUB = @POSUB@ RANLIB = @RANLIB@ VERSION = @VERSION@ ZLIBS = @ZLIBS@ -ZLIB_SUBDIR = @ZLIB_SUBDIR@ INCLUDES = -I$(top_srcdir)/include EXTRA_DIST = OPTIONS pubring.g10 diff --git a/g10/encode.c b/g10/encode.c index 04aebefdb..eea7345fa 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -182,7 +182,7 @@ encode_crypt( const char *filename, STRLIST remusr ) goto leave; } else if( opt.verbose ) - log_error("reading from '%s'\n", filename? filename: "[stdin]"); + log_info("reading from '%s'\n", filename? filename: "[stdin]"); if( !(out = open_outfile( filename, opt.armor? 1:0 )) ) { rc = G10ERR_CREATE_FILE; /* or user said: do not overwrite */ diff --git a/g10/export.c b/g10/export.c index d45c1285f..619d69958 100644 --- a/g10/export.c +++ b/g10/export.c @@ -31,17 +31,109 @@ #include "keydb.h" #include "memory.h" #include "util.h" +#include "main.h" /**************** - * Make a new keyring from all internal keyrings (if no user is given) - * or for all selected users. + * Export the public keys (to standard out or --outout). + * Depending on opt.armor the output is armored. + * If USERS is NULL, the complete ring wil. be exported. */ int export_pubkeys( STRLIST users ) { - log_fatal("Not yet implemented"); - return 0; + int rc = 0; + armor_filter_context_t afx; + compress_filter_context_t zfx; + IOBUF out = NULL; + PACKET pkt; + KBNODE keyblock = NULL; + KBNODE kbctx, node; + KBPOS kbpos; + STRLIST sl; + int all = !users; + int any=0; + + memset( &afx, 0, sizeof afx); + memset( &zfx, 0, sizeof zfx); + init_packet( &pkt ); + + if( !(out = open_outfile( NULL, 0 )) ) { + rc = G10ERR_CREATE_FILE; + goto leave; + } + + if( opt.armor ) { + afx.what = 1; + iobuf_push_filter( out, armor_filter, &afx ); + } + if( opt.compress ) + iobuf_push_filter( out, compress_filter, &zfx ); + + if( all ) { + rc = enum_keyblocks( 0, &kbpos, &keyblock ); + if( rc ) { + if( rc != -1 ) + log_error("enum_keyblocks(open) failed: %s\n", g10_errstr(rc) ); + goto leave; + } + all = 2; + } + + /* use the correct sequence. strlist_last,prev do work correct with + * NULL pointers :-) */ + for( sl=strlist_last(users); sl || all ; sl=strlist_prev( users, sl )) { + if( all ) { /* get the next user */ + rc = enum_keyblocks( 1, &kbpos, &keyblock ); + if( rc == -1 ) /* EOF */ + break; + if( rc ) { + log_error("enum_keyblocks(read) failed: %s\n", g10_errstr(rc)); + break; + } + } + else { + /* search the userid */ + rc = find_keyblock_byname( &kbpos, sl->d ); + if( rc ) { + log_error("%s: user not found: %s\n", sl->d, g10_errstr(rc) ); + rc = 0; + continue; + } + /* read the keyblock */ + rc = read_keyblock( &kbpos, &keyblock ); + } + + if( rc ) { + log_error("certificate read problem: %s\n", g10_errstr(rc)); + goto leave; + } + + /* and write it */ + for( kbctx=NULL; (node = walk_kbnode( keyblock, &kbctx, 0 )); ) { + if( (rc = build_packet( out, node->pkt )) ) { + log_error("build_packet(%d) failed: %s\n", + node->pkt->pkttype, g10_errstr(rc) ); + rc = G10ERR_WRITE_FILE; + goto leave; + } + } + any++; + } + if( rc == -1 ) + rc = 0; + + leave: + if( all == 2 ) + enum_keyblocks( 2, &kbpos, &keyblock ); /* close */ + release_kbnode( keyblock ); + if( rc || !any ) + iobuf_cancel(out); + else + iobuf_close(out); + if( !any ) + log_info("warning: nothing exported\n"); + return rc; } @@ -41,11 +41,85 @@ #include "status.h" +static ARGPARSE_OPTS opts[] = { + + { 300, NULL, 0, N_("\vCommands:\n ") }, + + { 's', "sign", 0, N_("make a signature")}, + { 539, "clearsign", 0, N_("make a clear text signature") }, + { 'b', "detach-sign", 0, N_("make a detached signature")}, + { 'e', "encrypt", 0, N_("encrypt data")}, + { 'c', "symmetric", 0, N_("encryption only with symmetric cipher")}, + { 507, "store", 0, N_("store only")}, + { 'd', "decrypt", 0, N_("decrypt data (default)")}, + { 'k', "list-keys", 0, N_("list keys")}, + { 508, "check-keys",0, N_("check signatures on a key in the keyring")}, + { 515, "fingerprint", 0, N_("show the fingerprints")}, + { 521, "list-packets",0,N_("list only the sequence of packets")}, + { 503, "gen-key", 0, N_("generate a new key pair")}, + { 506, "sign-key" ,0, N_("make a signature on a key in the keyring")}, + { 505, "delete-key",0, N_("remove key from the public keyring")}, + { 524, "edit-sig" ,0, N_("edit a key signature")}, + { 525, "change-passphrase", 0, N_("change the passphrase of your secret keyring")}, + { 537, "export" , 0, N_("export keys") }, + { 530, "import", 0 , N_("import/merge keys")}, + + { 301, NULL, 0, N_("\v\nOptions:\n ") }, + + { 'a', "armor", 0, N_("create ascii armored output")}, + { 'o', "output", 2, N_("use as output file")}, + { 'u', "local-user",2, N_("use this user-id to sign or decrypt")}, + { 'r', "remote-user", 2, N_("use this user-id for encryption")}, + { 'v', "verbose", 0, N_("verbose") }, + { 'z', NULL, 1, N_("set compress level (0 disables)") }, + { 't', "textmode", 0, N_("use canonical text mode")}, + { 'n', "dry-run", 0, N_("don't make any changes") }, + { 500, "batch", 0, N_("batch mode: never ask")}, + { 501, "yes", 0, N_("assume yes on most questions")}, + { 502, "no", 0, N_("assume no on most questions")}, + { 509, "keyring" ,2, N_("add this keyring to the list of keyrings")}, + { 517, "secret-keyring" ,2, N_("add this secret keyring to the list")}, + { 518, "options" , 2, N_("read options from file")}, + + { 510, "debug" ,4|16, N_("set debugging flags")}, + { 511, "debug-all" ,0, N_("enable full debugging")}, + { 512, "status-fd" ,1, N_("write status info to this fd") }, + { 534, "no-comment", 0, N_("do not write comment packets")}, + { 535, "completes-needed", 1, N_("(default is 1)")}, + { 536, "marginals-needed", 1, N_("(default is 3)")}, + { 527, "cipher-algo", 2 , N_("select default cipher algorithm")}, + { 528, "pubkey-algo", 2 , N_("select default puplic key algorithm")}, + { 529, "digest-algo", 2 , N_("select default message digest algorithm")}, + + { 302, NULL, 0, N_("\v\nExamples:\n\n" + " -se -r Bob [file] sign and encrypt for user Bob\n" + " -sat [file] make a clear text signature\n" + " -sb [file] make a detached signature\n" + " -k [userid] show keys\n" + " -kc [userid] show fingerprint\n" ) }, + + /* hidden options */ + { 532, "quick-random", 0, "\r"}, + { 526, "no-verbose", 0, "\r"}, + { 538, "trustdb-name", 2, "\r" }, + { 540, "no-secmem-warning", 0, "\r" }, /* used only by regression tests */ + { 519, "no-armor", 0, "\r"}, + { 520, "no-default-keyring", 0, "\r" }, + { 522, "no-greeting", 0, "\r" }, + { 523, "passphrase-fd",1, "\r" }, + { 541, "no-operation", 0, "\r" }, /* used by regression tests */ + + +{0} }; + + + + enum cmd_values { aNull = 0, aSym, aStore, aEncr, aKeygen, aSign, aSignEncr, aSignKey, aClearsign, aListPackets, aEditSig, aKMode, aKModeC, aChangePass, aImport, - aExport, + aExport, aCheckKeys, aNOP }; @@ -59,7 +133,7 @@ strusage( int level ) switch( level ) { case 10: case 0: p = "g10 - v" VERSION "; " - "Copyright 1997 Werner Koch (dd9jn)\n" ; break; + "Copyright 1998 Werner Koch (dd9jn)\n" ; break; case 13: p = "g10"; break; case 14: p = VERSION; break; case 1: @@ -105,7 +179,7 @@ i18n_init(void) static void wrong_args( const char *text) { - fputs(_("Usage: g10 [options] "),stderr); + fputs(_("usage: g10 [options] "),stderr); fputs(text,stderr); putc('\n',stderr); g10_exit(2); @@ -152,63 +226,28 @@ set_cmd( enum cmd_values *ret_cmd, enum cmd_values new_cmd ) } + +static void +check_opts(void) +{ + if( !opt.def_cipher_algo || check_cipher_algo(opt.def_cipher_algo) ) + log_error(_("selected cipher algorithm is invalid\n")); + if( !opt.def_pubkey_algo || check_pubkey_algo(opt.def_pubkey_algo) ) + log_error(_("selected pubkey algorithm is invalid\n")); + if( !opt.def_digest_algo || check_digest_algo(opt.def_digest_algo) ) + log_error(_("selected digest algorithm is invalid\n")); + if( opt.completes_needed < 1 ) + log_error(_("completes-needed must be greater than 0\n")); + if( opt.marginals_needed < 2 ) + log_error(_("marginals-needed must be greater than 1\n")); +} + + + + void main( int argc, char **argv ) { - static ARGPARSE_OPTS opts[] = { - { 'a', "armor", 0, N_("create ascii armored output")}, - { 'v', "verbose", 0, N_("verbose") }, - { 'z', NULL, 1, N_("set compress level (0 disables)") }, - { 'n', "dry-run", 0, N_("don't make any changes") }, - { 'c', "symmetric", 0, N_("do only a symmetric encryption")}, - { 'o', "output", 2, N_("use as output file")}, - { 500, "batch", 0, N_("batch mode: never ask")}, - { 501, "yes", 0, N_("assume yes on most questions")}, - { 502, "no", 0, N_("assume no on most questions")}, - { 503, "gen-key", 0, N_("generate a new key pair")}, - { 504, "add-key", 0, N_("add key to the public keyring")}, - { 505, "delete-key",0, N_("remove key from public keyring")}, - { 506, "sign-key" ,0, N_("make a signature on a key in the keyring")}, - { 507, "store", 0, N_("store only")}, - { 508, "check-key" ,0, N_("check signatures on a key in the keyring")}, - { 509, "keyring" ,2, N_("add this keyring to the list of keyrings")}, - { 's', "sign", 0, N_("make a signature")}, - { 't', "textmode", 0, N_("use canonical text mode")}, - { 'b', "detach-sign", 0, N_("make a detached signature")}, - { 'e', "encrypt", 0, N_("encrypt data")}, - { 'd', "decrypt", 0, N_("decrypt data (default)")}, - { 'u', "local-user",2, N_("use this user-id to sign or decrypt")}, - { 'r', "remote-user", 2, N_("use this user-id for encryption")}, - { 'k', NULL , 0, N_("list keys")}, - { 510, "debug" ,4|16, N_("set debugging flags")}, - { 511, "debug-all" ,0, N_("enable full debugging")}, - { 512, "status-fd" ,1, N_("write status info to this fd") }, - { 515, "fingerprint", 0, N_("show the fingerprints")}, - { 517, "secret-keyring" ,2, N_("add this secret keyring to the list")}, - { 518, "options" , 2, N_("read options from file")}, - { 519, "no-armor", 0, "\r"}, - { 520, "no-default-keyring", 0, "\r" }, - { 521, "list-packets",0,N_("list only the sequence of packets")}, - { 522, "no-greeting", 0, "\r" }, - { 523, "passphrase-fd",1, "\r" }, - { 524, "edit-sig" ,0, N_("edit a key signature")}, - { 525, "change-passphrase", 0, N_("change the passphrase of your secret keyring")}, - { 526, "no-verbose", 0, "\r"}, - { 527, "cipher-algo", 2 , N_("select default cipher algorithm")}, - { 528, "pubkey-algo", 2 , N_("select default puplic key algorithm")}, - { 529, "digest-algo", 2 , N_("select default message digest algorithm")}, - { 530, "import", 0 , N_("put public keys into the trustdb")}, - { 532, "quick-random", 0, "\r"}, - { 534, "no-comment", 0, N_("do not write comment packets")}, - { 535, "completes-needed", 1, N_("(default is 1)")}, - { 536, "marginals-needed", 1, N_("(default is 3)")}, - { 537, "export", 0, N_("export all or the given keys") }, - { 538, "trustdb-name", 2, "\r" }, - { 539, "clearsign", 0, N_("make a clear text signature") }, - { 540, "no-secmem-warning", 0, "\r" }, /* used only by regression tests */ - { 541, "no-operation", 0, "\r" }, /* used by regression tests */ - - {0} }; ARGPARSE_ARGS pargs; IOBUF a; int rc=0; @@ -236,6 +275,7 @@ main( int argc, char **argv ) * secmem_init() somewhere after the option parsing */ + log_set_name("g10"); i18n_init(); opt.compress = -1; /* defaults to standard compress level */ opt.def_cipher_algo = CIPHER_ALGO_BLOWFISH; @@ -278,9 +318,11 @@ main( int argc, char **argv ) if( parse_debug ) log_info(_("note: no default option file '%s'\n"), configname ); } - else - log_fatal(_("option file '%s': %s\n"), + else { + log_error(_("option file '%s': %s\n"), configname, strerror(errno) ); + g10_exit(1); + } m_free(configname); configname = NULL; } if( parse_debug && configname ) @@ -291,9 +333,7 @@ main( int argc, char **argv ) while( optfile_parse( configfp, configname, &configlineno, &pargs, opts) ) { switch( pargs.r_opt ) { - case 'v': opt.verbose++; - opt.list_sigs=1; - break; + case 'v': opt.verbose++; opt.list_sigs=1; break; case 'z': opt.compress = pargs.r.ret_int; break; case 'a': opt.armor = 1; opt.no_armor=0; break; case 'd': break; /* it is default */ @@ -322,7 +362,8 @@ main( int argc, char **argv ) case 503: set_cmd( &cmd, aKeygen); break; case 506: set_cmd( &cmd, aSignKey); break; case 507: set_cmd( &cmd, aStore); break; - case 508: opt.check_sigs = 1; opt.list_sigs = 1; break; + case 508: set_cmd( &cmd, aCheckKeys); + opt.check_sigs = 1; opt.list_sigs = 1; break; case 509: add_keyring(pargs.r.ret_str); nrings++; break; case 510: opt.debug |= pargs.r.ret_ulong; break; case 511: opt.debug = ~0; break; @@ -374,27 +415,8 @@ main( int argc, char **argv ) goto next_pass; } m_free( configname ); configname = NULL; - if( !opt.def_cipher_algo || check_cipher_algo(opt.def_cipher_algo) ) { - log_error(_("selected cipher algorithm is invalid\n")); - errors++; - } - if( !opt.def_pubkey_algo || check_pubkey_algo(opt.def_pubkey_algo) ) { - log_error(_("selected pubkey algorithm is invalid\n")); - errors++; - } - if( !opt.def_digest_algo || check_digest_algo(opt.def_digest_algo) ) { - log_error(_("selected digest algorithm is invalid\n")); - errors++; - } - if( opt.completes_needed < 1 ) { - log_error(_("completes-needed must be greater than 0\n")); - errors++; - } - if( opt.marginals_needed < 2 ) { - log_error(_("marginals-needed must be greater than 1\n")); - errors++; - } - if( errors ) + check_opts(); + if( log_get_errorcount(0) ) g10_exit(2); if( greeting ) { @@ -541,6 +563,7 @@ main( int argc, char **argv ) g10_errstr(rc) ); break; + case aCheckKeys: case aKMode: /* list keyring */ if( !argc ) { /* list the default public keyrings */ int i, seq=0; @@ -563,14 +586,23 @@ main( int argc, char **argv ) } } + else if( cmd == aCheckKeys ) { + log_error("will be soon: --check-keys user-ids\n"); + } else if( argc == 1) { /* list the given keyring */ if( !(a = iobuf_open(fname)) ) - log_fatal(_("can't open '%s'\n"), fname_print); - proc_packets( a ); - iobuf_close(a); + log_error(_("can't open '%s'\n"), fname_print); + else { + if( !opt.no_armor ) { + memset( &afx, 0, sizeof afx); + iobuf_push_filter( a, armor_filter, &afx ); + } + proc_packets( a ); + iobuf_close(a); + } } else - wrong_args(_("-k[v][v][v][c] [keyring]")); + wrong_args(_("-k[v][v][v][c] [keyring]") ); break; case aKeygen: /* generate a key (interactive) */ @@ -607,18 +639,20 @@ main( int argc, char **argv ) if( argc > 1 ) wrong_args(_("[filename]")); if( !(a = iobuf_open(fname)) ) - log_fatal(_("can't open '%s'\n"), fname_print); - if( !opt.no_armor ) { - /* push the armor filter, so it can peek at the input data */ - memset( &afx, 0, sizeof afx); - iobuf_push_filter( a, armor_filter, &afx ); - } - if( cmd == aListPackets ) { - set_packet_list_mode(1); - opt.list_packets=1; + log_error(_("can't open '%s'\n"), fname_print); + else { + if( !opt.no_armor ) { + /* push the armor filter, so it can peek at the input data */ + memset( &afx, 0, sizeof afx); + iobuf_push_filter( a, armor_filter, &afx ); + } + if( cmd == aListPackets ) { + set_packet_list_mode(1); + opt.list_packets=1; + } + proc_packets( a ); + iobuf_close(a); } - proc_packets( a ); - iobuf_close(a); break; } diff --git a/g10/import.c b/g10/import.c index 2cba74a5b..0474152d7 100644 --- a/g10/import.c +++ b/g10/import.c @@ -35,15 +35,34 @@ /**************** - * Import the public keys from the given filename. - * Import is a somewhat misleading name, as we (only) add informations - * about the public keys into aout trustdb. + * Import the public keys from the given filename. Input may be armored. + * This function rejects alls keys which are not valid self signed on at + * least one userid. Only user ids which are self signed will be imported. + * Other signatures are not not checked. + * + * Actually this functtion does a merge, it works like this: + * FIXME: add handling for revocation certs + * + * - get the keyblock + * - check self-signatures and remove all userids and their isgnatures + * without/invalid self-signatures. + * - reject the keyblock, if we have no valid userid. + * - See wether we have this key already in one of our pubrings. + * If not, simply add it to the default keyring. + * - Compare the key and the self-signatures of the new and the one in + * our keyring. If they are differen something weird is going on; + * ask what to do. + * - See wether we have only non-self-signature on one user id; if not + * ask the user what to do. + * - compare the signatures: If we already have this signature, check + * that they compare okay, if not issue a warning and ask the user. + * (consider to look at the timestamp and use the newest?) + * - Simply add the signature. Can't verify here because we may not have + * the signatures public key yet; verification is done when putting it + * into the trustdb, which is done automagically as soon as this pubkey + * is used. + * - Proceed with next signature. * - * NOTE: this function is not really needed and will be changed to - * a function which reads a plain textfile, describing a public - * key and its associated ownertrust. This can be used (together - * with the export function) to make a backup of the assigned - * ownertrusts. */ int import_pubkeys( const char *filename ) diff --git a/g10/kbnode.c b/g10/kbnode.c index dd4f0ce24..83ec50742 100644 --- a/g10/kbnode.c +++ b/g10/kbnode.c @@ -177,11 +177,12 @@ walk_kbnode( KBNODE root, KBNODE *context, int all ) do { if( !*context ) { *context = root; - return root; + n = root; + } + else { + n = (*context)->next; + *context = n; } - - n = (*context)->next; - *context = n; } while( !all && n && (n->private_flag & 1) ); return n; diff --git a/g10/keydb.h b/g10/keydb.h index ff0ecb528..ca54020cd 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -51,6 +51,8 @@ struct keyblock_pos_struct { int resno; /* resource number */ ulong offset; /* position information */ unsigned count; /* length of the keyblock in packets */ + IOBUF fp; /* used by enum_keyblocks */ + PACKET *pkt; /* ditto */ }; typedef struct keyblock_pos_struct KBPOS; @@ -144,6 +146,7 @@ int find_secret_keyblock_byname( KBPOS *kbpos, const char *username ); int lock_keyblock( KBPOS *kbpos ); void unlock_keyblock( KBPOS *kbpos ); int read_keyblock( KBPOS *kbpos, KBNODE *ret_root ); +int enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root ); int insert_keyblock( KBPOS *kbpos, KBNODE root ); int delete_keyblock( KBPOS *kbpos ); int update_keyblock( KBPOS *kbpos, KBNODE root ); diff --git a/g10/keygen.c b/g10/keygen.c index f9e68a083..1c9a2efbe 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -535,11 +535,11 @@ generate_keypair() /* 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 comment packet, followed by the userid and - * the self signature. + * 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("#created by G10 pre-release " VERSION ); - sec_root = make_comment_node("#created by G10 pre-release " VERSION ); + pub_root = make_comment_node("#"); delete_kbnode(pub_root, pub_root); + sec_root = make_comment_node("#"); delete_kbnode(sec_root, sec_root); tty_printf(_( "We need to generate a lot of random bytes. It is a good idea to perform\n" @@ -557,6 +557,12 @@ generate_keypair() rc = gen_dsa(nbits, pub_root, sec_root, dek, &skc ); else BUG(); + if( !rc ) { + add_kbnode( pub_root, + make_comment_node("#created by G10 release " VERSION )); + add_kbnode( sec_root, + make_comment_node("#created by G10 release " VERSION )); + } if( !rc ) write_uid(pub_root, uid ); if( !rc ) diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 2e3cf21be..0e13f6d18 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -437,6 +437,7 @@ parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) if( k->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { n = pktlen; k->d.elg.a = mpi_read(inp, &n, 0); pktlen -=n; + n = pktlen; k->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n; if( list_mode ) { printf("\telg a: "); @@ -502,6 +503,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, sig->d.elg.digest_start[1] = iobuf_get_noeof(inp); pktlen--; n = pktlen; sig->d.elg.a = mpi_read(inp, &n, 0 ); pktlen -=n; + n = pktlen; sig->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n; if( list_mode ) { printf("\tdigest algo %d, begin of digest %02x %02x\n", diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index 2f8fb45f4..0fcd9c21c 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -38,8 +38,10 @@ int get_session_key( PKT_pubkey_enc *k, DEK *dek ) { - int i, j, c, rc = 0; - MPI dek_frame = mpi_alloc_secure(40); + int rc = 0; + MPI plain_dek = NULL; + byte *frame = NULL; + unsigned n, nframe; u16 csum, csum2; PKT_secret_cert *skc = m_alloc_clear( sizeof *skc ); @@ -58,7 +60,8 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek ) skey.g = skc->d.elg.g; skey.y = skc->d.elg.y; skey.x = skc->d.elg.x; - elg_decrypt( dek_frame, k->d.elg.a, k->d.elg.b, &skey ); + plain_dek = mpi_alloc_secure( mpi_get_nlimbs(skey.p) ); + elg_decrypt( plain_dek, k->d.elg.a, k->d.elg.b, &skey ); memset( &skey, 0, sizeof skey ); } #ifdef HAVE_RSA_CIPHER @@ -74,7 +77,8 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek ) skey.q = skc->d.rsa.rsa_q; skey.d = skc->d.rsa.rsa_d; skey.u = skc->d.rsa.rsa_u; - rsa_secret( dek_frame, k->d.rsa.rsa_integer, &skey ); + plain_dek = mpi_alloc_secure( mpi_get_nlimbs(skey.n) ); + rsa_secret( plain_dek, k->d.rsa.rsa_integer, &skey ); memset( &skey, 0, sizeof skey ); } #endif/*HAVE_RSA_CIPHER*/ @@ -83,9 +87,10 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek ) goto leave; } free_secret_cert( skc ); skc = NULL; + frame = mpi_get_buffer( plain_dek, &nframe, NULL ); + mpi_free( plain_dek ); plain_dek = NULL; - - /* Now get the DEK (data encryption key) from the dek_frame + /* Now get the DEK (data encryption key) from the frame * * Old versions encode the DEK in in this format (msb is left): * @@ -101,51 +106,53 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek ) * CSUM */ if( DBG_CIPHER ) - log_mpidump("DEK frame:", dek_frame ); - for(i=0; mpi_getbyte(dek_frame, i) != -1; i++ ) + log_hexdump("DEK frame:", frame, nframe ); + for(n=0; n < nframe && !frame[n]; n++ ) /* skip leading zeroes */ ; - for(i--; i >= 0 && !(c=mpi_getbyte(dek_frame, i)); i--) - ; /* Skip leading zeroes */ - if( i < 16 ) + if( n + 7 > nframe ) { rc = G10ERR_WRONG_SECKEY; goto leave; } - if( c == 1 && mpi_getbyte(dek_frame,0) == 2 ) { + if( frame[n] == 1 && frame[nframe-1] == 2 ) { log_error("old encoding of DEK is not supported\n"); rc = G10ERR_CIPHER_ALGO; goto leave; } - if( c != 2 ) /* somethink is wrong */ + if( frame[n] != 2 ) /* somethink is wrong */ { rc = G10ERR_WRONG_SECKEY; goto leave; } - /* look for the zero byte */ - for(i--; i > 4 ; i-- ) - if( !mpi_getbyte(dek_frame,i) ) - break; - if( i <= 4 ) /* zero byte not found */ + for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */ + ; + n++; /* and the zero byte */ + if( n + 4 > nframe ) { rc = G10ERR_WRONG_SECKEY; goto leave; } - /* next byte indicates the used cipher */ - switch( mpi_getbyte(dek_frame, --i ) ) { + + dek->keylen = nframe - (n+1) - 2; + dek->algo = frame[n++]; + switch( dek->algo ) { case CIPHER_ALGO_IDEA: rc = G10ERR_NI_CIPHER; goto leave; case CIPHER_ALGO_BLOWFISH: - if( i != 22 ) /* length of blowfish is 20 (+2 bytes checksum) */ + if( dek->keylen != 20 ) { rc = G10ERR_WRONG_SECKEY; goto leave; } - dek->algo = CIPHER_ALGO_BLOWFISH; break; case CIPHER_ALGO_BLOWFISH128: - if( i != 18 ) /* length of blowfish-128 is 16 (+2 bytes checksum) */ + if( dek->keylen != 16 ) + { rc = G10ERR_WRONG_SECKEY; goto leave; } + break; + case CIPHER_ALGO_CAST: + if( dek->keylen < 5 || dek->keylen > 16 ) { rc = G10ERR_WRONG_SECKEY; goto leave; } - dek->algo = CIPHER_ALGO_BLOWFISH128; break; default: + dek->algo = 0; rc = G10ERR_CIPHER_ALGO; goto leave; } /* copy the key to DEK and compare the checksum */ - csum = mpi_getbyte(dek_frame, 1) << 8; - csum |= mpi_getbyte(dek_frame, 0); - dek->keylen = i - 2; - for( i--, csum2=0, j=0; i > 1; i-- ) - csum2 += dek->key[j++] = mpi_getbyte(dek_frame, i); + csum = frame[nframe-2] << 8; + csum |= frame[nframe-1]; + memcpy( dek->key, frame+n, dek->keylen ); + for( csum2=0, n=0; n < dek->keylen; n++ ) + csum2 += dek->key[n]; if( csum != csum2 ) { rc = G10ERR_WRONG_SECKEY; goto leave; @@ -154,7 +161,8 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek ) log_hexdump("DEK is:", dek->key, dek->keylen ); leave: - mpi_free(dek_frame); + mpi_free(plain_dek); + m_free(frame); if( skc ) free_secret_cert( skc ); return rc; diff --git a/g10/ringedit.c b/g10/ringedit.c index 141d8cf7f..adba3db0b 100644 --- a/g10/ringedit.c +++ b/g10/ringedit.c @@ -77,6 +77,7 @@ static int keyring_search( PACKET *pkt, KBPOS *kbpos, IOBUF iobuf ); static int keyring_search2( PUBKEY_FIND_INFO info, KBPOS *kbpos, const char *fname); static int keyring_read( KBPOS *kbpos, KBNODE *ret_root ); +static int keyring_enum( KBPOS *kbpos, KBNODE *ret_root ); static int keyring_copy( KBPOS *kbpos, int mode, KBNODE root ); @@ -297,6 +298,78 @@ read_keyblock( KBPOS *kbpos, KBNODE *ret_root ) return keyring_read( kbpos, ret_root ); } + +/**************** + * This functions can be used to read trough a complete keyring. + * Mode is: 0 = open + * 1 = read + * 2 = close + * all others are reserved! + * Note that you do not need a search prior to call this function, + * only handle is needed. + * NOTE: It is not alloed to do an insert/update/delte with this + * keyblock, if you want to do this, user search/read! + */ +int +enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root ) +{ + int rc = 0; + RESTBL *rentry; + + if( !mode || mode == 100 ) { + int i; + kbpos->fp = NULL; + if( !mode ) + i = 0; + else + i = kbpos->resno+1; + for(; i < MAX_RESOURCES; i++ ) + if( resource_table[i].used && !resource_table[i].secret ) + break; + if( i == MAX_RESOURCES ) + return -1; /* no resources */ + kbpos->resno = i; + rentry = check_pos( kbpos ); + kbpos->fp = iobuf_open( rentry->fname ); + if( !kbpos->fp ) { + log_error("can't open '%s'\n", rentry->fname ); + return G10ERR_OPEN_FILE; + } + kbpos->pkt = NULL; + } + else if( mode == 1 ) { + int cont; + do { + cont = 0; + if( !kbpos->fp ) + return G10ERR_GENERAL; + rc = keyring_enum( kbpos, ret_root ); + if( rc == -1 ) { + assert( !kbpos->pkt ); + rentry = check_pos( kbpos ); + assert(rentry); + /* close */ + enum_keyblocks(2, kbpos, ret_root ); + /* and open the next one */ + rc = enum_keyblocks(100, kbpos, ret_root ); + if( !rc ) + cont = 1; + } + } while(cont); + } + else if( kbpos->fp ) { + iobuf_close( kbpos->fp ); + kbpos->fp = NULL; + /* release pending packet */ + free_packet( kbpos->pkt ); + m_free( kbpos->pkt ); + } + return rc; +} + + + + /**************** * Insert the keyblock described by ROOT into the keyring described * by KBPOS. This actually appends the data to the keyfile. @@ -551,9 +624,8 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root ) if( rc ) release_kbnode( root ); - else { + else *ret_root = root; - } free_packet( pkt ); m_free( pkt ); iobuf_close(a); @@ -561,6 +633,69 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root ) } +static int +keyring_enum( KBPOS *kbpos, KBNODE *ret_root ) +{ + PACKET *pkt; + int rc; + RESTBL *rentry; + KBNODE root = NULL; + int in_cert = 0; + + if( !(rentry=check_pos(kbpos)) ) + return G10ERR_GENERAL; + + if( kbpos->pkt ) { + root = new_kbnode( kbpos->pkt ); + kbpos->pkt = NULL; + } + + pkt = m_alloc( sizeof *pkt ); + init_packet(pkt); + while( (rc=parse_packet(kbpos->fp, pkt)) != -1 ) { + if( rc ) { /* ignore errors */ + if( rc != G10ERR_UNKNOWN_PACKET ) { + log_error("read_keyblock: read error: %s\n", g10_errstr(rc) ); + rc = G10ERR_INV_KEYRING; + goto ready; + } + free_packet( pkt ); + continue; + } + /* make a linked list of all packets */ + switch( pkt->pkttype ) { + case PKT_PUBLIC_CERT: + case PKT_SECRET_CERT: + if( in_cert ) { /* store this packet */ + kbpos->pkt = pkt; + pkt = NULL; + goto ready; + } + in_cert = 1; + default: + if( !root ) + root = new_kbnode( pkt ); + else + add_kbnode( root, new_kbnode( pkt ) ); + pkt = m_alloc( sizeof *pkt ); + init_packet(pkt); + break; + } + } + ready: + if( rc == -1 && root ) + rc = 0; + + if( rc ) + release_kbnode( root ); + else + *ret_root = root; + free_packet( pkt ); + m_free( pkt ); + return rc; +} + + /**************** * Peromf insert/delete/update operation. @@ -579,6 +714,8 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root ) if( !(rentry = check_pos( kbpos )) ) return G10ERR_GENERAL; + if( kbpos->fp ) + BUG(); /* not allowed with such a handle */ /* open the source file */ fp = iobuf_open( rentry->fname ); diff --git a/g10/sign.c b/g10/sign.c index 52718b390..d6777442a 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -796,14 +796,14 @@ edit_keysigs( const char *username ) /* search the userid */ rc = find_keyblock_byname( &kbpos, username ); if( rc ) { - log_error("user '%s' not found\n", username ); + log_error("%s: user not found\n", username ); goto leave; } /* read the keyblock */ rc = read_keyblock( &kbpos, &keyblock ); if( rc ) { - log_error("error reading the certificate: %s\n", g10_errstr(rc) ); + log_error("%s: certificate read problem: %s\n", username, g10_errstr(rc) ); goto leave; } |