diff --git a/NEWS b/NEWS index 2925ab450..a2bec816c 100644 --- a/NEWS +++ b/NEWS @@ -35,11 +35,16 @@ Noteworthy changes in version 0.3.3 * gpg now disables core dumps. + * compress and symmetric cipher preferences are now used. + Because there is no 3DES yet, this is replaced by Blowfish. + * We have added the Twofish as an experimental cipher algorithm. Many thanks to Matthew Skala for doing this work. Twofish is the AES submission from Schneier et al.; see "www.counterpane.com/twofish.html" for more information. + * [talk about --emulate-encr-mpi-bug] + Noteworthy changes in version 0.3.2 diff --git a/README b/README index 240b319f1..8714eba43 100644 --- a/README +++ b/README @@ -22,7 +22,7 @@ "pub 1312G/FF3EAA0B 1998-02-09 Werner Koch " "Key fingerprint = 8489 6CD0 1851 0E33 45DA CD67 036F 11B8 FF3E AA0B" - My standard key is now: + My usual key is now: "pub 1024D/621CC013 1998-07-07 Werner Koch " "Key fingerprint = ECAF 7590 EB34 43B5 C7CF 3ACB 6C7E E1B8 621C C013" @@ -42,7 +42,8 @@ IDEA (which is patented worldwide) and RSA (which is patented in the United States until Sep 20, 2000). - GNUPG is in most aspects compatible with other OpenPGP implementations. + GNUPG is in almost all aspects compatible with other OpenPGP + implementations. The default algorithms are now DSA and ELGamal. ELGamal for signing is still available, but due to the larger size of such signatures it diff --git a/THANKS b/THANKS index d0c53d505..7c04f6aee 100644 --- a/THANKS +++ b/THANKS @@ -29,6 +29,7 @@ Nicolas Graner Nicolas.Graner@cri.u-psud.fr Oskari Jääskeläinen f33003a@cc.hut.fi Peter Gutmann pgut001@cs.auckland.ac.nz Ralph Gillen gillen@theochem.uni-duesseldorf.de +Serge Munhoven munhoven@mema.ucl.ac.be Steffen Ullrich ccrlphr@xensei.com Thomas Roessler roessler@guug.de Tom Spindler dogcow@home.merit.edu diff --git a/TODO b/TODO index e6cf8a71a..2af0c45fc 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,7 @@ * Fix Oscaris problems with the trustdb. + * Replace the SIGUSR1 stuff by semaphores to avoid loss of a signal. + * add test cases for invalid data (scrambled armor or other random data) * fix the expire stuff for v4 packets. @@ -8,14 +10,16 @@ sig) into a compressed packet - or should we only compress the data? what does pgp 5 do, what does OpenPGP say= - * invalid packets (Marco) + * invalid packets (Marco) und Markus Gruber * add some sanity checks to read_keyblock, so that we are sure that - the minimal requirements are met (?) + the minimal requirements are met (?) * what about the CR,LF in cleartext singatures? - * make preferences work + * decryption of message with multiple recipients does not work. + + * preferences of hash algorithms are not yet used. * rewrite --list-packets or put it into another tool. @@ -25,8 +29,6 @@ * Burn the buffers used by fopen(), or use read(2). Does this really make sense? - * enable a SIGSEGV handler while using zlib functions - * Change the buffering to a mbuf like scheme? Need it for PSST anyway. * add checking of armor trailers * remove all "Fixmes" @@ -40,3 +42,8 @@ * replace getkey.c#enum_secret_keys + * OpenBSD has sometimes problems reading from /dev/random. + + * change the fake_data stuff to mpi_set_opaque + + diff --git a/doc/DETAILS b/doc/DETAILS index 04236b7e9..d09871ec1 100644 --- a/doc/DETAILS +++ b/doc/DETAILS @@ -128,6 +128,7 @@ Record type 5: (pref record) 1 u32 LID; points to the directory record (and not to the uid record!). (or 0 for standard preference record) 1 u32 next + 30 byte preference data Record type 6 (sigrec) ------------- diff --git a/doc/gpg.1pod b/doc/gpg.1pod index 3cc3b24db..98863102d 100644 --- a/doc/gpg.1pod +++ b/doc/gpg.1pod @@ -130,8 +130,6 @@ B<--edit-key> I Remove a subkey. B Change the passphrase of the secret key. - B - Check signatures B I Toggle selection of user id with index I. Use 0 to deselect all. @@ -140,6 +138,8 @@ B<--edit-key> I Use 0 to deselect all. B Check all selected user ids. + B + List preferences. B Toggle between public and secret key listing. B @@ -316,7 +316,8 @@ B<--marginals-needed> I B<--cipher-algo> I Use I as cipher algorithm. Running the program with the option B<--verbose> yields a list of supported - algorithms. + algorithms. If this is not used the cipher algorithm is + selected from the preferences stored with the key. B<--digest-algo> I Use I as message digest algorithm. Running the @@ -329,6 +330,8 @@ B<--compress-algo> I version which is used by PGP. This is only used for new messages. The default algorithm may give better results because the window size is not limited to 8K. + If this is not used the OpenPGP behaviour is used; i.e. + the compression algorith is selected from the preferences. B<--passphrase-fd> I Read the passphrase from file descriptor I. If you use diff --git a/g10/ChangeLog b/g10/ChangeLog index 39e528de0..a907239b2 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,27 @@ +Wed Aug 5 11:54:37 1998 Werner Koch (wk@(none)) + + * g10.c (check_opts): Moved to main. Changed def_cipher_algo + semantics and chnaged all users. + + * pubkey-enc.c (get_sssion_key): New informational output + about preferences. + + * parse-packet.c (parse_symkeyenc): Fixed salted+iterated S2K + (parse_key): Ditto. + * build-packet.c (do_secret_key): Ditto. + (do_symkey_enc): Ditto. + +Tue Aug 4 08:59:10 1998 Werner Koch (wk@(none)) + + * getkey.c (enum_secret_keys): Now returns only primary keys. + + * getkey (lookup): Now sets the new namehash field. + + * parse-packet.c (parse_sig_subpkt2): New. + + * sign.c (sign_file): one-pass sigs are now emiited reverse. + Preference data is considered when selecting the compress algo. + Wed Jul 29 12:53:03 1998 Werner Koch (wk@(none)) * free-packet.c (copy_signature): New. diff --git a/g10/build-packet.c b/g10/build-packet.c index c7ed8fa2a..1ddb420ae 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -301,18 +301,24 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk ) iobuf_put(a, sk->protect.s2k.mode ); iobuf_put(a, sk->protect.s2k.hash_algo ); if( sk->protect.s2k.mode == 1 - || sk->protect.s2k.mode == 4 ) + || sk->protect.s2k.mode == 3 ) iobuf_write(a, sk->protect.s2k.salt, 8 ); - if( sk->protect.s2k.mode == 4 ) - write_32(a, sk->protect.s2k.count ); + if( sk->protect.s2k.mode == 3 ) + iobuf_put(a, sk->protect.s2k.count ); iobuf_write(a, sk->protect.iv, 8 ); } } else iobuf_put(a, 0 ); - for( ; i < nskey; i++ ) - mpi_write(a, sk->skey[i] ); - write_16(a, sk->csum ); + if( sk->is_protected && sk->version >= 4 + && !(opt.emulate_bugs & EMUBUG_ENCR_MPI) ) { + BUG(); + } + else { + for( ; i < nskey; i++ ) + mpi_write(a, sk->skey[i] ); + write_16(a, sk->csum ); + } leave: write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes, 1 ); @@ -331,17 +337,17 @@ do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ) assert( enc->version == 4 ); switch( enc->s2k.mode ) { - case 0: case 1: case 4: break; + case 0: case 1: case 3: break; default: log_bug("do_symkey_enc: s2k=%d\n", enc->s2k.mode ); } iobuf_put( a, enc->version ); iobuf_put( a, enc->cipher_algo ); iobuf_put( a, enc->s2k.mode ); iobuf_put( a, enc->s2k.hash_algo ); - if( enc->s2k.mode == 1 || enc->s2k.mode == 4 ) { + if( enc->s2k.mode == 1 || enc->s2k.mode == 3 ) { iobuf_write(a, enc->s2k.salt, 8 ); - if( enc->s2k.mode == 4 ) - write_32(a, enc->s2k.count); + if( enc->s2k.mode == 3 ) + iobuf_put(a, enc->s2k.count); } if( enc->seskeylen ) iobuf_write(a, enc->seskey, enc->seskeylen ); diff --git a/g10/encode.c b/g10/encode.c index 969e9afee..142a5e201 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -34,6 +34,7 @@ #include "util.h" #include "main.h" #include "filter.h" +#include "trustdb.h" #include "i18n.h" @@ -93,7 +94,9 @@ encode_simple( const char *filename, int mode ) s2k->mode = opt.rfc1991? 0:1; s2k->hash_algo = opt.def_digest_algo ? opt.def_digest_algo : DEFAULT_DIGEST_ALGO; - cfx.dek = passphrase_to_dek( NULL, opt.def_cipher_algo, s2k, 2 ); + cfx.dek = passphrase_to_dek( NULL, + opt.def_cipher_algo ? opt.def_cipher_algo + : DEFAULT_CIPHER_ALGO , s2k, 2 ); if( !cfx.dek || !cfx.dek->keylen ) { rc = G10ERR_PASSPHRASE; m_free(cfx.dek); @@ -218,7 +221,13 @@ encode_crypt( const char *filename, STRLIST remusr ) /* create a session key */ cfx.dek = m_alloc_secure( sizeof *cfx.dek ); - cfx.dek->algo = opt.def_cipher_algo; + if( !opt.def_cipher_algo ) { /* try to get it from the prefs */ + cfx.dek->algo = select_algo_from_prefs( pk_list, PREFTYPE_SYM ); + if( cfx.dek->algo == -1 ) + cfx.dek->algo = DEFAULT_CIPHER_ALGO; + } + else + cfx.dek->algo = opt.def_cipher_algo; make_session_key( cfx.dek ); if( DBG_CIPHER ) log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen ); @@ -253,8 +262,16 @@ encode_crypt( const char *filename, STRLIST remusr ) /* 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 ); + if( opt.compress ) { + int compr_algo = select_algo_from_prefs( pk_list, PREFTYPE_COMPR ); + if( !compr_algo ) + ; /* don't use compression */ + else { + if( compr_algo == 1 ) + zfx.algo = 1; /* default is 2 */ + iobuf_push_filter( out, compress_filter, &zfx ); + } + } /* do the work */ if( (rc = build_packet( out, &pkt )) ) @@ -293,7 +310,15 @@ encrypt_filter( void *opaque, int control, else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */ if( !efx->header_okay ) { efx->cfx.dek = m_alloc_secure( sizeof *efx->cfx.dek ); - efx->cfx.dek->algo = opt.def_cipher_algo; + + if( !opt.def_cipher_algo ) { /* try to get it from the prefs */ + efx->cfx.dek->algo = + select_algo_from_prefs( efx->pk_list, PREFTYPE_SYM ); + if( efx->cfx.dek->algo == -1 ) + efx->cfx.dek->algo = DEFAULT_CIPHER_ALGO; + } + else + efx->cfx.dek->algo = opt.def_cipher_algo; make_session_key( efx->cfx.dek ); if( DBG_CIPHER ) log_hexdump("DEK is: ", diff --git a/g10/free-packet.c b/g10/free-packet.c index 14a466556..e6b228117 100644 --- a/g10/free-packet.c +++ b/g10/free-packet.c @@ -30,6 +30,7 @@ #include "util.h" #include "cipher.h" #include "memory.h" +#include "options.h" void free_symkey_enc( PKT_symkey_enc *enc ) @@ -82,6 +83,10 @@ release_public_key_parts( PKT_public_key *pk ) mpi_free( pk->pkey[i] ); pk->pkey[i] = NULL; } + if( pk->namehash ) { + m_free(pk->namehash); + pk->namehash = NULL; + } } @@ -123,13 +128,22 @@ cp_data_block( byte *s ) PKT_public_key * -copy_public_key( PKT_public_key *d, PKT_public_key *s ) +copy_public_key_new_namehash( PKT_public_key *d, PKT_public_key *s, + const byte *namehash ) { int n, i; if( !d ) d = m_alloc(sizeof *d); memcpy( d, s, sizeof *d ); + if( namehash ) { + d->namehash = m_alloc( 20 ); + memcpy(d->namehash, namehash, 20 ); + } + else if( s->namehash ) { + d->namehash = m_alloc( 20 ); + memcpy(d->namehash, s->namehash, 20 ); + } n = pubkey_get_npkey( s->pubkey_algo ); if( !n ) d->pkey[0] = cp_fake_data(s->pkey[0]); @@ -140,6 +154,11 @@ copy_public_key( PKT_public_key *d, PKT_public_key *s ) return d; } +PKT_public_key * +copy_public_key( PKT_public_key *d, PKT_public_key *s ) +{ + return copy_public_key_new_namehash( d, s, NULL ); +} PKT_signature * copy_signature( PKT_signature *d, PKT_signature *s ) diff --git a/g10/g10.c b/g10/g10.c index 54dc39c2a..acc5bf691 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -173,6 +173,7 @@ static ARGPARSE_OPTS opts[] = { { 559, "always-trust", 0, "@"}, { 562, "emulate-checksum-bug", 0, "@"}, { 554, "run-as-shm-coprocess", 4, "@" }, + { 568, "emulate-encr-mpi-bug", 0, "@"}, {0} }; @@ -361,24 +362,6 @@ 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_digest_algo && check_digest_algo(opt.def_digest_algo) ) - log_error(_("selected digest algorithm is invalid\n")); - if( opt.def_compress_algo < 1 || opt.def_compress_algo > 2 ) - log_error(_("compress algorithm must be in range %d..%d\n"), 1, 2); - 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")); -} - - - - int main( int argc, char **argv ) { @@ -426,7 +409,7 @@ main( int argc, char **argv ) i18n_init(); opt.compress = -1; /* defaults to standard compress level */ /* fixme: set the next two to zero and decide where used */ - opt.def_cipher_algo = DEFAULT_CIPHER_ALGO; + opt.def_cipher_algo = 0; opt.def_digest_algo = 0; opt.def_compress_algo = 2; opt.completes_needed = 1; @@ -615,6 +598,7 @@ main( int argc, char **argv ) log_error("shared memory coprocessing is not available\n"); #endif break; + case 568: opt.emulate_bugs |= EMUBUG_ENCR_MPI; break; default : errors++; pargs.err = configfp? 1:2; break; } } @@ -657,12 +641,22 @@ main( int argc, char **argv ) if( def_cipher_string ) { opt.def_cipher_algo = string_to_cipher_algo(def_cipher_string); m_free(def_cipher_string); def_cipher_string = NULL; + if( check_cipher_algo(opt.def_cipher_algo) ) + log_error(_("selected cipher algorithm is invalid\n")); } if( def_digest_string ) { opt.def_digest_algo = string_to_digest_algo(def_digest_string); m_free(def_digest_string); def_digest_string = NULL; + if( check_digest_algo(opt.def_digest_algo) ) + log_error(_("selected digest algorithm is invalid\n")); } - check_opts(); + if( opt.def_compress_algo < 1 || opt.def_compress_algo > 2 ) + log_error(_("compress algorithm must be in range %d..%d\n"), 1, 2); + 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")); + if( log_get_errorcount(0) ) g10_exit(2); diff --git a/g10/getkey.c b/g10/getkey.c index 912c91906..72bb3d990 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -685,6 +685,8 @@ lookup( PKT_public_key *pk, int mode, u32 *keyid, KBNODE keyblock = NULL; KBPOS kbpos; int oldmode = set_packet_list_mode(0); + byte namehash[20]; + int use_namehash=0; rc = enum_keyblocks( 0, &kbpos, &keyblock ); if( rc ) { @@ -719,6 +721,10 @@ lookup( PKT_public_key *pk, int mode, u32 *keyid, u32 aki[2]; keyid_from_pk( kk->pkt->pkt.public_key, aki ); cache_user_id( k->pkt->pkt.user_id, aki ); + rmd160_hash_buffer( namehash, + k->pkt->pkt.user_id->name, + k->pkt->pkt.user_id->len ); + use_namehash = 1; k = kk; break; } @@ -799,7 +805,8 @@ lookup( PKT_public_key *pk, int mode, u32 *keyid, if( k ) { /* found */ assert( k->pkt->pkttype == PKT_PUBLIC_KEY || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ); - copy_public_key( pk, k->pkt->pkt.public_key ); + copy_public_key_new_namehash( pk, k->pkt->pkt.public_key, + use_namehash? namehash:NULL); add_stuff_from_selfsig( keyblock, k ); if( ret_keyblock ) { *ret_keyblock = keyblock; @@ -950,7 +957,7 @@ lookup_sk( PKT_secret_key *sk, int mode, u32 *keyid, const char *name ) /**************** - * Enumerate all secret keys. Caller must use these procedure: + * Enumerate all primary secret keys. Caller must use these procedure: * 1) create a void pointer and initialize it to NULL * 2) pass this void pointer by reference to this function * and provide space for the secret key (pass a buffer for sk) @@ -997,8 +1004,7 @@ enum_secret_keys( void **context, PKT_secret_key *sk ) while( (rc=parse_packet(c->iobuf, &pkt)) != -1 ) { if( rc ) ; /* e.g. unknown packet */ - else if( pkt.pkttype == PKT_SECRET_KEY - || pkt.pkttype == PKT_SECRET_SUBKEY ) { + else if( pkt.pkttype == PKT_SECRET_KEY ) { copy_secret_key( sk, pkt.pkt.secret_key ); set_packet_list_mode(save_mode); return 0; /* found */ diff --git a/g10/keydb.h b/g10/keydb.h index 85ab88b45..2d3f61f88 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -91,6 +91,7 @@ struct pubkey_find_info { int check_signatures_trust( PKT_signature *sig ); void release_pk_list( PK_LIST pk_list ); int build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned usage ); +int select_algo_from_prefs( PK_LIST pk_list, int preftype ); /*-- skclist.c --*/ void release_sk_list( SK_LIST sk_list ); diff --git a/g10/keyedit.c b/g10/keyedit.c index f61916bae..69685bfff 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -40,8 +40,9 @@ #include "status.h" #include "i18n.h" +static void show_prefs( KBNODE keyblock, PKT_user_id *uid ); static void show_key_with_all_names( KBNODE keyblock, - int only_marked, int with_fpr, int with_subkeys ); + int only_marked, int with_fpr, int with_subkeys, int with_prefs ); static void show_key_and_fingerprint( KBNODE keyblock ); static void show_fingerprint( PKT_public_key *pk ); static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock ); @@ -256,7 +257,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified ) } /* Ask whether we realy should sign these user id(s) */ tty_printf("\n"); - show_key_with_all_names( keyblock, 1, 1, 0 ); + show_key_with_all_names( keyblock, 1, 1, 0, 0 ); tty_printf("\n"); tty_printf(_( "Are you really sure that you want to sign this key\n" @@ -544,7 +545,7 @@ keyedit_menu( const char *username, STRLIST locusr ) enum cmdids { cmdNONE = 0, cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN, cmdDEBUG, cmdSAVE, cmdADDUID, cmdDELUID, cmdADDKEY, cmdDELKEY, - cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, + cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, cmdNOP }; static struct { const char *name; enum cmdids id; @@ -573,6 +574,7 @@ keyedit_menu( const char *username, STRLIST locusr ) { N_("toggle") , cmdTOGGLE , 1, N_("toggle between secret " "and public key listing") }, { N_("t" ) , cmdTOGGLE , 1, NULL }, + { N_("pref") , cmdPREF , 0, N_("list preferences") }, { N_("passwd") , cmdPASSWD , 1, N_("change the passphrase") }, { N_("trust") , cmdTRUST , 0, N_("change the ownertrust") }, @@ -625,7 +627,7 @@ keyedit_menu( const char *username, STRLIST locusr ) tty_printf("\n"); if( redisplay ) { - show_key_with_all_names( cur_keyblock, 0, 0, 1 ); + show_key_with_all_names( cur_keyblock, 0, 0, 1, 0 ); tty_printf("\n"); redisplay = 0; } @@ -670,7 +672,7 @@ keyedit_menu( const char *username, STRLIST locusr ) break; case cmdQUIT: - if( !modified ) + if( !modified && !sec_modified ) goto leave; if( !cpr_get_answer_is_yes("keyedit.save",_("Save changes? ")) ) { if( cpr_enabled() @@ -680,11 +682,13 @@ keyedit_menu( const char *username, STRLIST locusr ) } /* fall thru */ case cmdSAVE: - if( modified ) { - rc = update_keyblock( &keyblockpos, keyblock ); - if( rc ) { - log_error(_("update failed: %s\n"), g10_errstr(rc) ); - break; + if( modified || sec_modified ) { + if( modified ) { + rc = update_keyblock( &keyblockpos, keyblock ); + if( rc ) { + log_error(_("update failed: %s\n"), g10_errstr(rc) ); + break; + } } if( sec_modified ) { rc = update_keyblock( &sec_keyblockpos, sec_keyblock ); @@ -807,7 +811,7 @@ keyedit_menu( const char *username, STRLIST locusr ) break; case cmdTRUST: - show_key_with_all_names( keyblock, 0, 0, 1 ); + show_key_with_all_names( keyblock, 0, 0, 1, 0 ); tty_printf("\n"); if( edit_ownertrust( find_kbnode( keyblock, PKT_PUBLIC_KEY )->pkt->pkt.public_key->local_id, 1 ) ) @@ -816,6 +820,10 @@ keyedit_menu( const char *username, STRLIST locusr ) * are updated immediately */ break; + case cmdPREF: + show_key_with_all_names( keyblock, 0, 0, 0, 1 ); + break; + case cmdNOP: break; @@ -833,6 +841,45 @@ keyedit_menu( const char *username, STRLIST locusr ) } +/**************** + * show preferences of a public keyblock. + */ +static void +show_prefs( KBNODE keyblock, PKT_user_id *uid ) +{ + KBNODE node = find_kbnode( keyblock, PKT_PUBLIC_KEY ); + PKT_public_key *pk; + byte *p; + int i; + size_t n; + byte namehash[20]; + + if( !node ) + return; /* is a secret keyblock */ + pk = node->pkt->pkt.public_key; + if( !pk->local_id ) { + log_error("oops: no LID\n"); + return; + } + + rmd160_hash_buffer( namehash, uid->name, uid->len ); + + p = get_pref_data( pk->local_id, namehash, &n ); + if( !p ) + return; + + tty_printf(" "); + for(i=0; i < n; i+=2 ) { + if( p[i] ) + tty_printf( " %c%d", p[i] == PREFTYPE_SYM ? 'S' : + p[i] == PREFTYPE_HASH ? 'H' : + p[i] == PREFTYPE_COMPR ? 'Z' : '?', p[i+1]); + } + tty_printf("\n"); + + m_free(p); +} + /**************** * Display the key a the user ids, if only_marked is true, do only @@ -840,7 +887,7 @@ keyedit_menu( const char *username, STRLIST locusr ) */ static void show_key_with_all_names( KBNODE keyblock, int only_marked, - int with_fpr, int with_subkeys ) + int with_fpr, int with_subkeys, int with_prefs ) { KBNODE node; int i; @@ -850,6 +897,15 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, if( node->pkt->pkttype == PKT_PUBLIC_KEY || (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) { PKT_public_key *pk = node->pkt->pkt.public_key; + int otrust=0, trust=0; + + if( node->pkt->pkttype == PKT_PUBLIC_KEY ) { + /* do it here, so that debug messages don't clutter the + * output */ + trust = query_trust_info(pk); + otrust = get_ownertrust_info( pk->local_id ); + } + tty_printf("%s%c %4u%c/%08lX created: %s expires: %s", node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub", (node->flag & NODFLG_SELKEY)? '*':' ', @@ -859,9 +915,6 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, datestr_from_pk(pk), expirestr_from_pk(pk) ); if( node->pkt->pkttype == PKT_PUBLIC_KEY ) { - int otrust, trust; - trust = query_trust_info(pk); - otrust = get_ownertrust_info( pk->local_id ); tty_printf(" trust: %c/%c", otrust, trust ); if( with_fpr ) show_fingerprint( pk ); @@ -896,6 +949,8 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, tty_printf("(%d) ", i); tty_print_string( uid->name, uid->len ); tty_printf("\n"); + if( with_prefs ) + show_prefs( keyblock, uid ); } } } diff --git a/g10/keygen.c b/g10/keygen.c index 4ff81b7f5..7780abfb1 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -32,6 +32,7 @@ #include "ttyio.h" #include "options.h" #include "keydb.h" +#include "status.h" #include "i18n.h" @@ -389,7 +390,7 @@ ask_algo( int *ret_v4, int addmode ) *ret_v4 = 1; for(;;) { - answer = tty_get(_("Your selection? ")); + answer = cpr_get("keygen.algo",_("Your selection? ")); tty_kill_prompt(); algo = *answer? atoi(answer): 1; m_free(answer); @@ -433,7 +434,7 @@ ask_keysize( int algo ) " highest suggested keysize is 2048 bits\n"), pubkey_algo_to_string(algo) ); for(;;) { - answer = tty_get(_("What keysize do you want? (1024) ")); + answer = cpr_get("keygen.size",_("What keysize do you want? (1024) ")); tty_kill_prompt(); nbits = *answer? atoi(answer): 1024; m_free(answer); @@ -441,7 +442,7 @@ ask_keysize( int algo ) tty_printf(_("DSA only allows keysizes from 512 to 1024\n")); else if( nbits < 768 ) tty_printf(_("keysize too small; 768 is smallest value allowed.\n")); - else if( nbits > 2048 ) { + else if( nbits > 2048 && !cpr_enabled() ) { tty_printf(_("Keysizes larger than 2048 are not suggested because " "computations take REALLY long!\n")); if( tty_get_answer_is_yes(_( @@ -452,7 +453,7 @@ ask_keysize( int algo ) break; } } - else if( nbits > 1536 ) { + else if( nbits > 1536 && !cpr_enabled() ) { if( tty_get_answer_is_yes(_( "Do you really need such a large keysize? ")) ) break; @@ -494,7 +495,7 @@ ask_valid_days() int mult; m_free(answer); - answer = tty_get(_("Key is valid for? (0) ")); + answer = cpr_get("keygen.valid",_("Key is valid for? (0) ")); tty_kill_prompt(); trim_spaces(answer); if( !*answer ) @@ -517,7 +518,8 @@ ask_valid_days() add_days_to_timestamp( make_timestamp(), valid_days ))); } - if( tty_get_answer_is_yes(_("Is this correct (y/n)? ")) ) + if( !cpr_enabled() + && tty_get_answer_is_yes(_("Is this correct (y/n)? ")) ) break; } m_free(answer); @@ -556,7 +558,7 @@ ask_user_id( int mode ) if( !aname ) { for(;;) { m_free(aname); - aname = tty_get(_("Real name: ")); + aname = cpr_get("keygen.name",_("Real name: ")); trim_spaces(aname); tty_kill_prompt(); if( strpbrk( aname, "<([])>" ) ) @@ -572,7 +574,7 @@ ask_user_id( int mode ) if( !amail ) { for(;;) { m_free(amail); - amail = tty_get(_("Email address: ")); + amail = cpr_get("keygen.email",_("Email address: ")); trim_spaces(amail); strlwr(amail); tty_kill_prompt(); @@ -592,7 +594,7 @@ ask_user_id( int mode ) if( !acomment ) { for(;;) { m_free(acomment); - acomment = tty_get(_("Comment: ")); + acomment = cpr_get("keygen.comment",_("Comment: ")); trim_spaces(acomment); tty_kill_prompt(); if( !*acomment ) @@ -622,9 +624,16 @@ ask_user_id( int mode ) /* fixme: add a warning if this user-id already exists */ for(;;) { char *ansstr = N_("NnCcEeOoQq"); - answer = tty_get(_( - "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? ")); - tty_kill_prompt(); + + if( cpr_enabled() ) { + answer = m_strdup(ansstr+6); + answer[1] = 0; + } + else { + answer = tty_get(_( + "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? ")); + tty_kill_prompt(); + } if( strlen(answer) > 1 ) ; else if( *answer == ansstr[0] || *answer == ansstr[1] ) { @@ -950,7 +959,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) assert(algo); nbits = ask_keysize( algo ); ndays = ask_valid_days(); - if( !tty_get_answer_is_yes( _("Really create? ") ) ) + if( !cpr_enabled() && !tty_get_answer_is_yes( _("Really create? ") ) ) goto leave; if( passphrase ) { diff --git a/g10/mainproc.c b/g10/mainproc.c index e7dabf5e9..ccc529693 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -171,6 +171,7 @@ proc_pubkey_enc( CTX c, PACKET *pkt ) PKT_pubkey_enc *enc; int result = 0; + /* check whether the secret key is available and store in this case */ c->last_was_session_key = 1; enc = pkt->pkt.pubkey_enc; /*printf("enc: encrypted by a pubkey with keyid %08lX\n", enc->keyid[1] );*/ @@ -208,7 +209,9 @@ proc_encrypted( CTX c, PACKET *pkt ) /*printf("dat: %sencrypted data\n", c->dek?"":"conventional ");*/ if( !c->dek && !c->last_was_session_key ) { /* assume this is old conventional encrypted data */ - c->dek = passphrase_to_dek( NULL, opt.def_cipher_algo, NULL, 0 ); + c->dek = passphrase_to_dek( NULL, + opt.def_cipher_algo ? opt.def_cipher_algo + : DEFAULT_CIPHER_ALGO, NULL, 0 ); } else if( !c->dek ) result = G10ERR_NO_SECKEY; @@ -223,6 +226,8 @@ proc_encrypted( CTX c, PACKET *pkt ) } else { log_error(_("decryption failed: %s\n"), g10_errstr(result)); + /* FIXME: if this is secret key not available, try with + * other keys */ } free_packet(pkt); c->last_was_session_key = 0; @@ -707,7 +712,9 @@ do_proc_packets( CTX c, IOBUF a ) while( (rc=parse_packet(a, pkt)) != -1 ) { /* cleanup if we have an illegal data structure */ if( c->dek && pkt->pkttype != PKT_ENCRYPTED ) { - log_error("oops: valid pubkey enc packet not followed by data\n"); + /* FIXME: do we need to ave it in case we have no secret + * key for one of the next reciepents- we should check it + * here. */ m_free(c->dek); c->dek = NULL; /* burn it */ } @@ -889,7 +896,7 @@ proc_tree( CTX c, KBNODE node ) /* ask for file and hash it */ if( c->sigs_only ) rc = hash_datafiles( c->mfx.md, c->signed_data, c->sigfilename, - n1->pkt->pkt.onepass_sig->sig_class == 0x01 ); + n1? (n1->pkt->pkt.onepass_sig->sig_class == 0x01):0 ); else rc = ask_for_detached_datafile( &c->mfx, iobuf_get_fname(c->iobuf)); diff --git a/g10/options.h b/g10/options.h index 630e43f44..862ed4146 100644 --- a/g10/options.h +++ b/g10/options.h @@ -56,6 +56,7 @@ struct { #define EMUBUG_GPGCHKSUM 1 +#define EMUBUG_ENCR_MPI 2 #define DBG_PACKET_VALUE 1 /* debug packet reading/writing */ #define DBG_MPI_VALUE 2 /* debug mpi details */ diff --git a/g10/packet.h b/g10/packet.h index 6a35cd89e..495e72216 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -112,6 +112,7 @@ typedef struct { byte pubkey_usage; /* for now only used to pass it to getkey() */ ulong local_id; /* internal use, valid if > 0 */ u32 keyid[2]; /* calculated by keyid_from_pk() */ + byte *namehash; /* if != NULL: found by this name */ MPI pkey[PUBKEY_MAX_NPKEY]; } PKT_public_key; @@ -235,6 +236,8 @@ int copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff ); int skip_some_packets( IOBUF inp, unsigned n ); const byte *parse_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, size_t *ret_n ); +const byte *parse_sig_subpkt2( PKT_signature *sig, + sigsubpkttype_t reqtype, size_t *ret_n ); /*-- build-packet.c --*/ int build_packet( IOBUF inp, PACKET *pkt ); @@ -257,6 +260,9 @@ void free_user_id( PKT_user_id *uid ); void free_comment( PKT_comment *rem ); void free_packet( PACKET *pkt ); PKT_public_key *copy_public_key( PKT_public_key *d, PKT_public_key *s ); +PKT_public_key *copy_public_key_new_namehash( PKT_public_key *d, + PKT_public_key *s, + const byte *namehash ); PKT_secret_key *copy_secret_key( PKT_secret_key *d, PKT_secret_key *s ); PKT_signature *copy_signature( PKT_signature *d, PKT_signature *s ); PKT_user_id *copy_user_id( PKT_user_id *d, PKT_user_id *s ); diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 60e0042da..396486f23 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -461,6 +461,25 @@ read_rest( IOBUF inp, ulong *r_pktlen ) return p; } +static void * +read_rest2( IOBUF inp, size_t pktlen ) +{ + byte *p; + int i; + + if( iobuf_in_block_mode(inp) ) { + log_error("read_rest: can't store stream data\n"); + p = NULL; + } + else { + p = m_alloc( pktlen ); + for(i=0; pktlen; pktlen--, i++ ) + p[i] = iobuf_get(inp); + } + return p; +} + + static int parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) @@ -491,8 +510,8 @@ parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) case 1: /* salted s2k */ minlen = 8; break; - case 4: /* iterated+salted s2k */ - minlen = 12; + case 3: /* iterated+salted s2k */ + minlen = 9; break; default: log_error("unknown S2K %d\n", s2kmode ); @@ -509,12 +528,12 @@ parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) k->cipher_algo = cipher_algo; k->s2k.mode = s2kmode; k->s2k.hash_algo = hash_algo; - if( s2kmode == 1 || s2kmode == 4 ) { + if( s2kmode == 1 || s2kmode == 3 ) { for(i=0; i < 8 && pktlen; i++, pktlen-- ) k->s2k.salt[i] = iobuf_get_noeof(inp); } - if( s2kmode == 4 ) { - k->s2k.count = read_32(inp); pktlen -= 4; + if( s2kmode == 3 ) { + k->s2k.count = iobuf_get(inp); pktlen--; } k->seskeylen = seskeylen; for(i=0; i < seskeylen && pktlen; i++, pktlen-- ) @@ -524,11 +543,11 @@ parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) if( list_mode ) { printf(":symkey enc packet: version %d, cipher %d, s2k %d, hash %d\n", version, cipher_algo, s2kmode, hash_algo); - if( s2kmode == 1 || s2kmode == 4 ) { + if( s2kmode == 1 || s2kmode == 3 ) { printf("\tsalt "); for(i=0; i < 8; i++ ) printf("%02x", k->s2k.salt[i]); - if( s2kmode == 4 ) + if( s2kmode == 3 ) printf(", count %lu\n", (ulong)k->s2k.count ); printf("\n"); } @@ -675,6 +694,10 @@ parse_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, size_t *ret_n ) if( n < 8 ) break; return buffer; + case SIGSUBPKT_PREF_SYM: + case SIGSUBPKT_PREF_HASH: + case SIGSUBPKT_PREF_COMPR: + return buffer; case SIGSUBPKT_PRIV_ADD_SIG: /* because we use private data, we check the GNUPG marker */ if( n < 24 ) @@ -693,6 +716,19 @@ parse_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, size_t *ret_n ) } +const byte * +parse_sig_subpkt2( PKT_signature *sig, sigsubpkttype_t reqtype, size_t *ret_n ) +{ + const byte *p; + + p = parse_sig_subpkt( sig->hashed_data, reqtype, ret_n ); + if( !p ) + p = parse_sig_subpkt( sig->unhashed_data, reqtype, ret_n ); + return p; +} + + + static int parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, PKT_signature *sig ) @@ -779,7 +815,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, log_error("signature packet without timestamp\n"); else sig->timestamp = buffer_to_u32(p); - p = parse_sig_subpkt( sig->unhashed_data, SIGSUBPKT_ISSUER, NULL ); + p = parse_sig_subpkt2( sig, SIGSUBPKT_ISSUER, NULL ); if( !p ) log_error("signature packet without keyid\n"); else { @@ -959,7 +995,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, } - if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) { + if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) { PKT_secret_key *sk = pkt->pkt.secret_key; byte temp[8]; @@ -990,7 +1026,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, sk->protect.s2k.hash_algo = iobuf_get_noeof(inp); pktlen--; switch( sk->protect.s2k.mode ) { case 1: - case 4: + case 3: for(i=0; i < 8 && pktlen; i++, pktlen-- ) temp[i] = iobuf_get_noeof(inp); memcpy(sk->protect.s2k.salt, temp, 8 ); @@ -1001,7 +1037,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, break; case 1: if( list_mode ) printf( "\tsalted S2K" ); break; - case 4: if( list_mode ) printf( "\titer+salt S2K" ); + case 3: if( list_mode ) printf( "\titer+salt S2K" ); break; default: if( list_mode ) @@ -1016,7 +1052,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, sk->protect.algo, sk->protect.s2k.hash_algo ); if( sk->protect.s2k.mode == 1 - || sk->protect.s2k.mode == 4 ) { + || sk->protect.s2k.mode == 3 ) { printf(", salt: "); for(i=0; i < 8; i++ ) printf("%02x", sk->protect.s2k.salt[i]); @@ -1024,13 +1060,13 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, putchar('\n'); } - if( sk->protect.s2k.mode == 4 ) { - if( pktlen < 4 ) { + if( sk->protect.s2k.mode == 3 ) { + if( pktlen < 1 ) { rc = G10ERR_INVALID_PACKET; goto leave; } - sk->protect.s2k.count = read_32(inp); - pktlen -= 4; + sk->protect.s2k.count = iobuf_get(inp); + pktlen--; } } @@ -1066,25 +1102,37 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, * If the user is so careless, not to protect his secret key, * we can assume, that he operates an open system :=(. * So we put the key into secure memory when we unprotect it. */ - - for(i=npkey; i < nskey; i++ ) { - n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n; - if( sk->is_protected ) - mpi_set_protect_flag(sk->skey[i]); + if( is_v4 && sk->is_protected && !(opt.emulate_bugs & EMUBUG_ENCR_MPI)){ + /* ugly; the length is encrypted too, so wee read all + * stuff up to the end of the packet into the first + * skey element */ + sk->skey[npkey] = mpi_set_opaque(NULL, + read_rest2(inp, pktlen), pktlen ); + pktlen = 0; if( list_mode ) { - printf( "\tskey[%d]: ", i); - if( sk->is_protected ) - printf( "[encrypted]\n"); - else { - mpi_print(stdout, sk->skey[i], mpi_print_mode ); - putchar('\n'); - } + printf("\tencrypted stuff follows\n"); } } + else { /* v3 method: the mpi length is not encrypted */ + for(i=npkey; i < nskey; i++ ) { + n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n; + if( sk->is_protected ) + mpi_set_protect_flag(sk->skey[i]); + if( list_mode ) { + printf( "\tskey[%d]: ", i); + if( sk->is_protected ) + printf( "[encrypted]\n"); + else { + mpi_print(stdout, sk->skey[i], mpi_print_mode ); + putchar('\n'); + } + } + } - sk->csum = read_16(inp); pktlen -= 2; - if( list_mode ) { - printf("\tchecksum: %04hx\n", sk->csum); + sk->csum = read_16(inp); pktlen -= 2; + if( list_mode ) { + printf("\tchecksum: %04hx\n", sk->csum); + } } } else { diff --git a/g10/passphrase.c b/g10/passphrase.c index ad8ca7681..f0e2f2544 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -195,7 +195,7 @@ hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create ) assert( s2k->hash_algo ); dek->keylen = 0; md = md_open( s2k->hash_algo, 1); - if( s2k->mode == 1 || s2k->mode == 4 ) { + if( s2k->mode == 1 || s2k->mode == 3 ) { if( create ) randomize_buffer(s2k->salt, 8, 1); md_write( md, s2k->salt, 8 ); diff --git a/g10/pkclist.c b/g10/pkclist.c index dbbcbbdd8..4e58f125c 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -512,3 +512,102 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned usage ) } +/**************** + * Return -1 if we could not find an algorithm. + */ +int +select_algo_from_prefs( PK_LIST pk_list, int preftype ) +{ + PK_LIST pkr; + u32 bits[8]; + byte *pref = NULL; + size_t npref; + int i, j; + int compr_hack=0; + int any; + + if( !pk_list ) + return -1; + + memset( bits, ~0, 8 * sizeof *bits ); + for( pkr = pk_list; pkr; pkr = pkr->next ) { + u32 mask[8]; + + memset( mask, 0, 8 * sizeof *mask ); + if( !pkr->pk->local_id ) + BUG(); /* if this occurs, we can use get_ownertrust to set it */ + if( preftype == PREFTYPE_SYM ) + bits[0] = (1<<2); /* 3DES is implicitly there */ + m_free(pref); + pref = get_pref_data( pkr->pk->local_id, pkr->pk->namehash, &npref); + any = 0; + if( pref ) { + /*log_hexdump("raw: ", pref, npref );*/ + for(i=0; i+1 < npref; i+=2 ) { + if( pref[i] == preftype ) { + mask[pref[i+1]/32] |= 1 << (pref[i+1]%32); + any = 1; + } + } + } + if( (!pref || !any) && preftype == PREFTYPE_COMPR ) { + mask[0] |= 3; /* asume no_compression and old pgp */ + compr_hack = 1; + } + + /*log_debug("mask=%08lX%08lX%08lX%08lX%08lX%08lX%08lX%08lX\n", + (ulong)mask[7], (ulong)mask[6], (ulong)mask[5], (ulong)mask[4], + (ulong)mask[3], (ulong)mask[2], (ulong)mask[1], (ulong)mask[0]);*/ + for(i=0; i < 8; i++ ) + bits[i] &= mask[i]; + /*log_debug("bits=%08lX%08lX%08lX%08lX%08lX%08lX%08lX%08lX\n", + (ulong)bits[7], (ulong)bits[6], (ulong)bits[5], (ulong)bits[4], + (ulong)bits[3], (ulong)bits[2], (ulong)bits[1], (ulong)bits[0]);*/ + } + /* usable algorithms are now in bits + * We now use the last key from pk_list to select + * the algorithm we want to use. there are no + * preferences for the last key, we select the one + * corresponding to first set bit. + */ + i = -1; + any = 0; + if( pref ) { + for(j=0; j+1 < npref; j+=2 ) { + if( pref[j] == preftype ) { + any = 1; + if( (bits[pref[j+1]/32] & (1<<(pref[j+1]%32))) ) { + i = pref[j+1]; + break; + } + } + } + } + if( !pref || !any ) { + for(j=0; j < 256; j++ ) + if( (bits[j/32] & (1<<(j%32))) ) { + i = j; + break; + } + } + /*log_debug("prefs of type %d: selected %d\n", preftype, i );*/ + if( compr_hack && !i ) { + /* selected no compression, but we should check whether + * algorithm 1 is also available (the ordering is not relevant + * in this case). */ + if( bits[0] & (1<<1) ) + i = 1; /* yep; we can use compression algo 1 */ + } + + if( preftype == PREFTYPE_SYM && i == CIPHER_ALGO_3DES ) { + i = CIPHER_ALGO_BLOWFISH; + if( opt.verbose ) + log_info("replacing 3DES by Blowfish\n"); + } + + + m_free(pref); + return i; +} + + diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index 90cd26036..98ad2d3ae 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -28,6 +28,7 @@ #include "packet.h" #include "mpi.h" #include "keydb.h" +#include "trustdb.h" #include "cipher.h" #include "status.h" @@ -124,6 +125,20 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek ) } if( DBG_CIPHER ) log_hexdump("DEK is:", dek->key, dek->keylen ); + /* check that the algo is in the preferences */ + { + PKT_public_key *pk = m_alloc_clear( sizeof *pk ); + if( (rc = get_pubkey( pk, k->keyid )) ) + log_error("public key problem: %s\n", g10_errstr(rc) ); + else if( !pk->local_id && query_trust_record(pk) ) + log_error("can't check algorithm against preferences\n"); + else if( dek->algo != CIPHER_ALGO_3DES + && !is_algo_in_prefs( pk->local_id, PREFTYPE_SYM, dek->algo ) ) + log_info("note: cipher algorithm %d not found in preferences\n", + dek->algo ); + free_public_key( pk ); + rc = 0; + } leave: mpi_free(plain_dek); diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index 6bffb7843..679d029cf 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -67,19 +67,48 @@ do_check( PKT_secret_key *sk ) memcpy(save_iv, sk->protect.iv, 8 ); cipher_decrypt( cipher_hd, sk->protect.iv, sk->protect.iv, 8 ); csum = 0; - for(i=pubkey_get_npkey(sk->pubkey_algo); - i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { - buffer = mpi_get_secure_buffer( sk->skey[i], &nbytes, NULL ); - cipher_sync( cipher_hd ); - assert( mpi_is_protected(sk->skey[i]) ); - cipher_decrypt( cipher_hd, buffer, buffer, nbytes ); - mpi_set_buffer( sk->skey[i], buffer, nbytes, 0 ); - mpi_clear_protect_flag( sk->skey[i] ); - csum += checksum_mpi( sk->skey[i] ); - m_free( buffer ); + if( sk->version >= 4 && !(opt.emulate_bugs & EMUBUG_ENCR_MPI) ) { + int ndata; + byte *p, *data; + + i = pubkey_get_npkey(sk->pubkey_algo); + assert( mpi_is_opaque( sk->skey[i] ) ); + p = mpi_get_opaque( sk->skey[i], &ndata ); + data = m_alloc_secure( ndata ); + cipher_decrypt( cipher_hd, data, p, ndata ); + mpi_free( sk->skey[i] ); sk->skey[i] = NULL ; + p = data; + csum = checksum( data, ndata); + if( ndata < 2 ) + log_bug("not enough bytes for checksum\n"); + sk->csum = data[ndata-2] << 8 | data[ndata-1]; + /* must check it here otherwise the mpi_read_xx would fail + * because the length das an abritary value */ + if( sk->csum == csum ) { + for( ; i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { + nbytes = ndata; + sk->skey[i] = mpi_read_from_buffer(p, &nbytes, 1 ); + ndata -= nbytes; + p += nbytes; + } + } + m_free(data); } - if( opt.emulate_bugs & EMUBUG_GPGCHKSUM ) { - csum = sk->csum; + else { + for(i=pubkey_get_npkey(sk->pubkey_algo); + i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { + buffer = mpi_get_secure_buffer( sk->skey[i], &nbytes, NULL ); + cipher_sync( cipher_hd ); + assert( mpi_is_protected(sk->skey[i]) ); + cipher_decrypt( cipher_hd, buffer, buffer, nbytes ); + mpi_set_buffer( sk->skey[i], buffer, nbytes, 0 ); + mpi_clear_protect_flag( sk->skey[i] ); + csum += checksum_mpi( sk->skey[i] ); + m_free( buffer ); + } + if( opt.emulate_bugs & EMUBUG_GPGCHKSUM ) { + csum = sk->csum; + } } cipher_close( cipher_hd ); /* now let's see whether we have used the right passphrase */ @@ -190,21 +219,26 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek ) cipher_setkey( cipher_hd, dek->key, dek->keylen ); cipher_setiv( cipher_hd, NULL ); cipher_encrypt( cipher_hd, sk->protect.iv, sk->protect.iv, 8 ); - /* NOTE: we always recalculate the checksum because there are some - * test releases which calculated it wrong */ - csum = 0; - for(i=pubkey_get_npkey(sk->pubkey_algo); - i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { - csum += checksum_mpi_counted_nbits( sk->skey[i] ); - buffer = mpi_get_buffer( sk->skey[i], &nbytes, NULL ); - cipher_sync( cipher_hd ); - assert( !mpi_is_protected(sk->skey[i]) ); - cipher_encrypt( cipher_hd, buffer, buffer, nbytes ); - mpi_set_buffer( sk->skey[i], buffer, nbytes, 0 ); - mpi_set_protect_flag( sk->skey[i] ); - m_free( buffer ); + if( sk->version >= 4 && !(opt.emulate_bugs & EMUBUG_ENCR_MPI) ) { + BUG(); + } + else { + /* NOTE: we always recalculate the checksum because there + * are some * test releases which calculated it wrong */ + csum = 0; + for(i=pubkey_get_npkey(sk->pubkey_algo); + i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { + csum += checksum_mpi_counted_nbits( sk->skey[i] ); + buffer = mpi_get_buffer( sk->skey[i], &nbytes, NULL ); + cipher_sync( cipher_hd ); + assert( !mpi_is_protected(sk->skey[i]) ); + cipher_encrypt( cipher_hd, buffer, buffer, nbytes ); + mpi_set_buffer( sk->skey[i], buffer, nbytes, 0 ); + mpi_set_protect_flag( sk->skey[i] ); + m_free( buffer ); + } + sk->csum = csum; } - sk->csum = csum; sk->is_protected = 1; cipher_close( cipher_hd ); } diff --git a/g10/sign.c b/g10/sign.c index 2aa9468e9..a5034c702 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -35,6 +35,7 @@ #include "main.h" #include "filter.h" #include "ttyio.h" +#include "trustdb.h" #include "i18n.h" @@ -118,6 +119,8 @@ only_old_style( SK_LIST sk_list ) return old_style; } + + /**************** * Sign the files whose names are in FILENAME. * If DETACHED has the value true, @@ -150,6 +153,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, SK_LIST sk_rover = NULL; int multifile = 0; int old_style = opt.rfc1991; + int compr_algo = -1; /* unknown */ memset( &afx, 0, sizeof afx); @@ -176,6 +180,8 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, if( encrypt ) { if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC )) ) goto leave; + if( !old_style ) + compr_algo = select_algo_from_prefs( pk_list, PREFTYPE_COMPR ); } /* prepare iobufs */ @@ -227,16 +233,31 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, } if( opt.compress && !outfile && ( !detached || opt.compress_sigs) ) { - if( old_style ) - zfx.algo = 1; - iobuf_push_filter( out, compress_filter, &zfx ); + if( !compr_algo ) + ; /* don't use compression */ + else { + if( old_style || compr_algo == 1 ) + zfx.algo = 1; + iobuf_push_filter( out, compress_filter, &zfx ); + } } if( !detached && !old_style ) { - /* loop over the secret certificates and build headers */ - for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { + int skcount=0; + /* loop over the secret certificates and build headers + * The specs now say that the data should be bracket by + * the onepass-sig and signature-packet; so we muts build it + * here in reverse order */ + for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) + skcount++; + for( ; skcount; skcount-- ) { PKT_secret_key *sk; PKT_onepass_sig *ops; + int i = 0; + + for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) + if( ++i == skcount ) + break; sk = sk_rover->sk; ops = m_alloc_clear( sizeof *ops ); @@ -244,7 +265,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, ops->digest_algo = hash_for(sk->pubkey_algo); ops->pubkey_algo = sk->pubkey_algo; keyid_from_sk( sk, ops->keyid ); - ops->last = !sk_rover->next; + ops->last = skcount == 1; init_packet(&pkt); pkt.pkttype = PKT_ONEPASS_SIG; @@ -259,7 +280,6 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, } } - /* setup the inner packet */ if( detached ) { if( multifile ) { diff --git a/g10/signal.c b/g10/signal.c index be831b338..c491329b4 100644 --- a/g10/signal.c +++ b/g10/signal.c @@ -60,7 +60,7 @@ got_fatal_signal( int sig ) fprintf( stderr, "\n%s: %s caught ... exiting\n", log_get_name(), signal_name(sig) ); secmem_term(); - exit( 2 ); + exit( 8 ); } @@ -94,6 +94,7 @@ init_signals() do_sigaction( SIGHUP, &nact ); do_sigaction( SIGTERM, &nact ); do_sigaction( SIGQUIT, &nact ); + do_sigaction( SIGSEGV, &nact ); nact.sa_handler = got_usr_signal; sigaction( SIGUSR1, &nact, NULL ); } diff --git a/g10/status.c b/g10/status.c index 744f98de6..8660613c3 100644 --- a/g10/status.c +++ b/g10/status.c @@ -113,8 +113,7 @@ init_shm_coprocessing ( ulong requested_shm_size, int lock_mem ) log_fatal("too much shared memory requested; only 8k are allowed\n"); shm_size = 4096 /* one page for us */ + requested_shm_size; - /* FIXME: Need other permissions ... */ - shm_id = shmget( IPC_PRIVATE, shm_size, IPC_CREAT | 0777 ); + shm_id = shmget( IPC_PRIVATE, shm_size, IPC_CREAT | 0700 ); if ( shm_id == -1 ) log_fatal("can't get %uk of shared memory: %s\n", (unsigned)shm_size/1024, strerror(errno)); diff --git a/g10/tdbio.c b/g10/tdbio.c index 381d0b2ec..034e092e3 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -356,6 +356,7 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp ) { int i; ulong rnum = rec->recnum; + byte *p; fprintf(fp, "rec %5lu, ", rnum ); @@ -405,9 +406,15 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp ) putc('\n', fp); break; case RECTYPE_PREF: - fprintf(fp, "pref %lu, next=%lu\n", - rec->r.uid.lid, - rec->r.uid.next); + fprintf(fp, "pref %lu, next=%lu,", + rec->r.pref.lid, rec->r.pref.next); + for(i=0,p=rec->r.pref.data; i < ITEMS_PER_PREF_RECORD; i+=2,p+=2 ) { + if( *p ) + fprintf(fp, " %c%d", *p == PREFTYPE_SYM ? 'S' : + *p == PREFTYPE_HASH ? 'H' : + *p == PREFTYPE_COMPR ? 'Z' : '?', p[1]); + } + putc('\n', fp); break; case RECTYPE_SIG: fprintf(fp, "sig %lu, next=%lu,", @@ -537,6 +544,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) case RECTYPE_PREF: /* preference record */ rec->r.pref.lid = buftoulong(p); p += 4; rec->r.pref.next = buftoulong(p); p += 4; + memcpy( rec->r.pref.data, p, 30 ); break; case RECTYPE_SIG: rec->r.sig.lid = buftoulong(p); p += 4; @@ -638,6 +646,7 @@ tdbio_write_record( TRUSTREC *rec ) case RECTYPE_PREF: ulongtobuf(p, rec->r.pref.lid); p += 4; ulongtobuf(p, rec->r.pref.next); p += 4; + memcpy( p, rec->r.pref.data, 30 ); break; case RECTYPE_SIG: diff --git a/g10/tdbio.h b/g10/tdbio.h index 6fb0e545c..0cbb851f2 100644 --- a/g10/tdbio.h +++ b/g10/tdbio.h @@ -26,6 +26,10 @@ #define SIGS_PER_RECORD ((TRUST_RECORD_LEN-10)/5) #define ITEMS_PER_HTBL_RECORD ((TRUST_RECORD_LEN-2)/4) #define ITEMS_PER_HLST_RECORD ((TRUST_RECORD_LEN-6)/5) +#define ITEMS_PER_PREF_RECORD (TRUST_RECORD_LEN-10) +#if ITEMS_PER_PREF_RECORD % 2 + #error ITEMS_PER_PREF_RECORD must be even +#endif #define MAX_LIST_SIGS_DEPTH 20 @@ -40,7 +44,6 @@ #define RECTYPE_HLST 11 - #define DIRF_CHECKED 1 /* everything has been checked, the other bits are valid */ #define DIRF_MISKEY 2 /* some keys are missing, so they could not be checked*/ @@ -91,10 +94,11 @@ struct trust_record { byte uidflags; byte namehash[20]; /* ripemd hash of the username */ } uid; - struct { /* preference reord */ + struct { /* preference record */ ulong lid; /* point back to the directory record */ /* or 0 for a glocal pref record */ ulong next; /* points to next pref record */ + byte data[ITEMS_PER_PREF_RECORD]; } pref; struct { /* signature record */ ulong lid; diff --git a/g10/trustdb.c b/g10/trustdb.c index d1f0fd051..cc94ad8e1 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -1593,8 +1593,6 @@ check_trust( PKT_public_key *pk, unsigned *r_trustlevel ) u32 keyid[2]; - if( DBG_TRUST ) - log_info("check_trust() called.\n"); keyid_from_pk( pk, keyid ); /* get the pubkey record */ @@ -1762,6 +1760,90 @@ get_ownertrust_info( ulong lid ) } +byte * +get_pref_data( ulong lid, const byte *namehash, size_t *ret_n ) +{ + TRUSTREC rec; + ulong recno; + int rc; + + if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) { + log_error("get_pref_data: read dir record failed\n"); + return NULL; + } + + for( recno=rec.r.dir.uidlist; recno; recno = rec.r.uid.next ) { + rc = tdbio_read_record( recno, &rec, RECTYPE_UID ); + if( rc ) { + log_error("get_pref_data: read uid record failed: %s\n", + g10_errstr(rc)); + return NULL; + } + if( rec.r.uid.prefrec + && ( !namehash || !memcmp(namehash, rec.r.uid.namehash, 20) )) { + byte *buf; + /* found the correct one or the first one */ + rc = tdbio_read_record( rec.r.uid.prefrec, &rec, RECTYPE_PREF ); + if( rc ) { + log_error("get_pref_data: read pref record failed: %s\n", + g10_errstr(rc)); + return NULL; + } + if( rec.r.pref.next ) + log_info("warning: can't yet handle long pref records\n"); + buf = m_alloc( ITEMS_PER_PREF_RECORD ); + memcpy( buf, rec.r.pref.data, ITEMS_PER_PREF_RECORD ); + *ret_n = ITEMS_PER_PREF_RECORD; + return buf; + } + } + return NULL; +} + + + +/**************** + * Check whether the algorithm is in one of the pref records + */ +int +is_algo_in_prefs( ulong lid, int preftype, int algo ) +{ + TRUSTREC rec; + ulong recno; + int i, rc; + byte *pref; + + if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) { + log_error("is_algo_in_prefs: read dir record failed\n"); + return 0; + } + + for( recno=rec.r.dir.uidlist; recno; recno = rec.r.uid.next ) { + rc = tdbio_read_record( recno, &rec, RECTYPE_UID ); + if( rc ) { + log_error("is_algo_in_prefs: read uid record failed: %s\n", + g10_errstr(rc)); + return 0; + } + if( rec.r.uid.prefrec ) { + rc = tdbio_read_record( rec.r.uid.prefrec, &rec, RECTYPE_PREF ); + if( rc ) { + log_error("is_algo_in_prefs: read pref record failed: %s\n", + g10_errstr(rc)); + return 0; + } + if( rec.r.pref.next ) + log_info("warning: can't yet handle long pref records\n"); + pref = rec.r.pref.data; + for(i=0; i+1 < ITEMS_PER_PREF_RECORD; i+=2 ) { + if( pref[i] == preftype && pref[i+1] == algo ) + return 1; + } + } + } + return 0; +} + /**************** * This function simply looks for the key in the trustdb @@ -1909,8 +1991,40 @@ insert_trust_record( PKT_public_key *orig_pk ) rc = 0; } else { /* build the prefrecord */ + static struct { + sigsubpkttype_t subpkttype; + int preftype; + } prefs[] = { + { SIGSUBPKT_PREF_SYM, PREFTYPE_SYM }, + { SIGSUBPKT_PREF_HASH, PREFTYPE_HASH }, + { SIGSUBPKT_PREF_COMPR, PREFTYPE_COMPR }, + { 0, 0 } + }; + const byte *s; + size_t n; + int k, i; assert(uidlist); + assert(!uidlist->help_pref); uidlist->mark |= 1; /* mark valid */ + + i = 0; + for(k=0; prefs[k].subpkttype; k++ ) { + s = parse_sig_subpkt2( sig, prefs[k].subpkttype, &n ); + if( s ) { + while( n ) { + if( !i || i >= ITEMS_PER_PREF_RECORD ) { + rec = m_alloc_clear( sizeof *rec ); + rec->rectype = RECTYPE_PREF; + rec->next = uidlist->help_pref; + uidlist->help_pref = rec; + i = 0; + } + rec->r.pref.data[i++] = prefs[k].preftype; + rec->r.pref.data[i++] = *s++; + n--; + } + } + } } } else if( 0 /* is revocation sig etc */ ) { @@ -1959,13 +2073,15 @@ insert_trust_record( PKT_public_key *orig_pk ) rec->r.uid.lid = dirrec.recnum; rec->recnum = tdbio_new_recnum(); /* (preference records) */ - for( rec2 = rec->help_pref; rec2; rec2 = rec2->next ) { - rec2->r.pref.lid = dirrec.recnum; - rec2->recnum = tdbio_new_recnum(); + if( rec->help_pref ) { + for( rec2 = rec->help_pref; rec2; rec2 = rec2->next ) { + rec2->r.pref.lid = dirrec.recnum; + rec2->recnum = tdbio_new_recnum(); + } + for( rec2 = rec->help_pref; rec2->next; rec2 = rec2->next ) + rec2->next->r.pref.next = rec2->recnum; + rec->r.uid.prefrec = rec2->recnum; } - for( rec2 = rec->help_pref; rec2; rec2 = rec2->next ) - rec2->r.pref.next = rec2->next? rec2->next->recnum : 0; - rec->r.uid.prefrec = rec->help_pref? rec->help_pref->recnum : 0; } for(rec=uidlist_head; rec; rec = rec->next ) rec->r.uid.next = rec->next? rec->next->recnum : 0; diff --git a/g10/trustdb.h b/g10/trustdb.h index 3f24cd514..fc470073f 100644 --- a/g10/trustdb.h +++ b/g10/trustdb.h @@ -35,6 +35,11 @@ #define TRUST_FLAG_REVOKED 32 /* r: revoked */ +#define PREFTYPE_SYM 1 +#define PREFTYPE_HASH 2 +#define PREFTYPE_COMPR 3 + + /*-- trustdb.c --*/ void list_trustdb(const char *username); void list_trust_path( int max_depth, const char *username ); @@ -47,6 +52,8 @@ int query_trust_info( PKT_public_key *pk ); int enum_trust_web( void **context, ulong *lid ); int get_ownertrust( ulong lid, unsigned *r_otrust ); int get_ownertrust_info( ulong lid ); +byte *get_pref_data( ulong lid, const byte *namehash, size_t *ret_n ); +int is_algo_in_prefs( ulong lid, int preftype, int algo ); int keyid_from_lid( ulong lid, u32 *keyid ); int query_trust_record( PKT_public_key *pk ); int insert_trust_record( PKT_public_key *pk ); diff --git a/include/mpi.h b/include/mpi.h index 6e0e42eaa..d4cb56cae 100644 --- a/include/mpi.h +++ b/include/mpi.h @@ -50,6 +50,7 @@ typedef struct mpi_struct { int sign; /* indicates a negative number */ unsigned flags; /* bit 0: array must be allocated in secure memory space */ /* bit 1: the mpi is encrypted */ + /* bit 2: the limb is a pointer to some m_alloced data */ mpi_limb_t *d; /* array with the limbs */ } *MPI; @@ -80,6 +81,9 @@ typedef struct mpi_struct { void mpi_resize( MPI a, unsigned nlimbs ); MPI mpi_copy( MPI a ); #endif +#define mpi_is_opaque(a) ((a) && ((a)->flags&4)) +MPI mpi_set_opaque( MPI a, void *p, int len ); +void *mpi_get_opaque( MPI a, int *len ); #define mpi_is_protected(a) ((a) && ((a)->flags&2)) #define mpi_set_protect_flag(a) ((a)->flags |= 2) #define mpi_clear_protect_flag(a) ((a)->flags &= ~2) @@ -100,6 +104,7 @@ int mpi_write( IOBUF out, MPI a ); #else MPI mpi_read(IOBUF inp, unsigned *nread, int secure); #endif +MPI mpi_read_from_buffer(byte *buffer, unsigned *ret_nread, int secure); int mpi_fromstr(MPI val, const char *str); int mpi_print( FILE *fp, MPI a, int mode ); u32 mpi_get_keyid( MPI a, u32 *keyid ); diff --git a/mpi/ChangeLog b/mpi/ChangeLog index babbabdf9..3fc0b3329 100644 --- a/mpi/ChangeLog +++ b/mpi/ChangeLog @@ -1,3 +1,12 @@ +Wed Aug 5 15:11:12 1998 Werner Koch (wk@(none)) + + * mpicoder.c (mpi_read_from_buffer): New. + + * mpiutil.c (mpi_set_opaque): New. + (mpi_get_opaque): New. + (mpi_copy): Changed to support opauqe flag + (mpi_free): Ditto. + Sat Jul 4 10:11:11 1998 Werner Koch (wk@isil.d.shuttle.de) * mpiutil.c (mpi_clear): Reset flags. diff --git a/mpi/mpicoder.c b/mpi/mpicoder.c index eba82a287..2775f5be8 100644 --- a/mpi/mpicoder.c +++ b/mpi/mpicoder.c @@ -123,6 +123,50 @@ mpi_read(IOBUF inp, unsigned *ret_nread, int secure) } +MPI +mpi_read_from_buffer(byte *buffer, unsigned *ret_nread, int secure) +{ + int i, j; + unsigned nbits, nbytes, nlimbs, nread=0; + mpi_limb_t a; + MPI val = MPI_NULL; + + if( *ret_nread < 2 ) + goto leave; + nbits = buffer[0] << 8 | buffer[1]; + if( nbits > MAX_EXTERN_MPI_BITS ) { + log_error("mpi too large (%u bits)\n", nbits); + goto leave; + } + buffer += 2; + nread = 2; + + nbytes = (nbits+7) / 8; + nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; + val = secure? mpi_alloc_secure( nlimbs ) + : mpi_alloc( nlimbs ); + i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; + i %= BYTES_PER_MPI_LIMB; + val->nbits = nbits; + j= val->nlimbs = nlimbs; + val->sign = 0; + for( ; j > 0; j-- ) { + a = 0; + for(; i < BYTES_PER_MPI_LIMB; i++ ) { + if( ++nread > *ret_nread ) + log_bug("mpi larger than buffer"); + a <<= 8; + a |= *buffer++; + } + i = 0; + val->d[j-1] = a; + } + + leave: + *ret_nread = nread; + return val; +} + /**************** * Make an mpi from a character string. diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c index c9af50561..f2f1726c4 100644 --- a/mpi/mpiutil.c +++ b/mpi/mpiutil.c @@ -193,12 +193,16 @@ mpi_free( MPI a ) return; if( DBG_MEMORY ) log_debug("mpi_free\n" ); - #ifdef M_DEBUG - mpi_debug_free_limb_space(a->d, info); - #else - mpi_free_limb_space(a->d); - #endif - if( a->flags & ~3 ) + if( a->flags & 4 ) + m_free( a->d ); + else { + #ifdef M_DEBUG + mpi_debug_free_limb_space(a->d, info); + #else + mpi_free_limb_space(a->d); + #endif + } + if( a->flags & ~7 ) log_bug("invalid flag value in mpi\n"); m_free(a); } @@ -232,6 +236,47 @@ mpi_set_secure( MPI a ) } +MPI +mpi_set_opaque( MPI a, void *p, int len ) +{ + if( !a ) { + #ifdef M_DEBUG + a = mpi_debug_alloc(0,"alloc_opaque"); + #else + a = mpi_alloc(0); + #endif + } + + if( a->flags & 4 ) + m_free( a->d ); + else { + #ifdef M_DEBUG + mpi_debug_free_limb_space(a->d, "alloc_opaque"); + #else + mpi_free_limb_space(a->d); + #endif + } + + a->d = p; + a->alloced = 0; + a->nlimbs = 0; + a->nbits = len; + a->flags = 4; + return a; +} + + +void * +mpi_get_opaque( MPI a, int *len ) +{ + if( !(a->flags & 4) ) + log_bug("mpi_get_opaque on normal mpi\n"); + if( len ) + *len = a->nbits; + return a->d; +} + + /**************** * Note: This copy function should not interpret the MPI * but copy it transparently. @@ -246,7 +291,13 @@ mpi_copy( MPI a ) int i; MPI b; - if( a ) { + if( a && (a->flags & 4) ) { + void *p = m_is_secure(a->d)? m_alloc_secure( a->nbits ) + : m_alloc( a->nbits ); + memcpy( p, a->d, a->nbits ); + b = mpi_set_opaque( NULL, p, a->nbits ); + } + else if( a ) { #ifdef M_DEBUG b = mpi_is_secure(a)? mpi_debug_alloc_secure( a->nlimbs, info ) : mpi_debug_alloc( a->nlimbs, info ); diff --git a/tools/shmtest.c b/tools/shmtest.c index 3f56669d6..5d8e01910 100644 --- a/tools/shmtest.c +++ b/tools/shmtest.c @@ -103,15 +103,6 @@ main(int argc, char **argv) if( argc < 1 ) my_usage(); - #if 0 - shm_ID = atoi( argv[1] ); - pool = shmat( shm_ID, 0, 0 ); - if( pool == (void*)-1 ) - log_fatal("shmat of %d failed: %s\n", shm_ID, strerror(errno)); - log_info("attached to %p id=%d\n", pool, shm_ID ); - getchar(); - #endif - for(n=0,i=1; i < argc; i++ ) n += strlen(argv[i]) + 1; p = m_alloc( 100 + n ); diff --git a/util/ChangeLog b/util/ChangeLog index aa9afe6e3..ece073420 100644 --- a/util/ChangeLog +++ b/util/ChangeLog @@ -1,3 +1,7 @@ +Mon Aug 3 17:06:00 1998 Werner Koch (wk@(none)) + + * secmem.c (MAP_ANON): Add a macro test + Wed Jul 29 14:53:34 1998 Werner Koch (wk@(none)) * ttyio.c (tty_get_answer_is_yes): New. diff --git a/util/iobuf.c b/util/iobuf.c index 3067ac433..6ad001334 100644 --- a/util/iobuf.c +++ b/util/iobuf.c @@ -706,6 +706,8 @@ iobuf_pop_filter( IOBUF a, int (*f)(void *opaque, int control, m_free(a->d.buf); memcpy(a,b, sizeof *a); m_free(b); + if( DBG_IOBUF ) + log_debug("iobuf-%d.%d: popped filter\n", a->no, a->subno ); } else if( !b->chain ) { /* remove the last iobuf from the chain */ log_bug("Ohh jeee, trying to remove a head filter\n"); diff --git a/util/secmem.c b/util/secmem.c index 583c96201..d78fabecf 100644 --- a/util/secmem.c +++ b/util/secmem.c @@ -35,6 +35,9 @@ #include "util.h" #include "i18n.h" +#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) + #define MAP_ANONYMOUS MAP_ANON +#endif #define DEFAULT_POOLSIZE 8196 @@ -105,10 +108,10 @@ init_pool( size_t n) if( disable_secmem ) log_bug("secure memory is disabled"); - #if HAVE_MMAP && defined(MAP_ANONYMOUS) + #if HAVE_MMAP && defined(MAP_ANON) poolsize = (poolsize + 4095) & ~4095; pool = mmap( 0, poolsize, PROT_READ|PROT_WRITE, - MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + MAP_PRIVATE|MAP_ANON, -1, 0); if( pool == (void*)-1 ) log_error("can't mmap pool of %u bytes: %s - using malloc\n", (unsigned)poolsize, strerror(errno));