intermediate check in
authorWerner Koch <wk@gnupg.org>
Wed, 5 Aug 1998 16:51:59 +0000 (16:51 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 5 Aug 1998 16:51:59 +0000 (16:51 +0000)
38 files changed:
NEWS
README
THANKS
TODO
doc/DETAILS
doc/gpg.1pod
g10/ChangeLog
g10/build-packet.c
g10/encode.c
g10/free-packet.c
g10/g10.c
g10/getkey.c
g10/keydb.h
g10/keyedit.c
g10/keygen.c
g10/mainproc.c
g10/options.h
g10/packet.h
g10/parse-packet.c
g10/passphrase.c
g10/pkclist.c
g10/pubkey-enc.c
g10/seckey-cert.c
g10/sign.c
g10/signal.c
g10/status.c
g10/tdbio.c
g10/tdbio.h
g10/trustdb.c
g10/trustdb.h
include/mpi.h
mpi/ChangeLog
mpi/mpicoder.c
mpi/mpiutil.c
tools/shmtest.c
util/ChangeLog
util/iobuf.c
util/secmem.c

diff --git a/NEWS b/NEWS
index 2925ab4..a2bec81 100644 (file)
--- 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 240b319..8714eba 100644 (file)
--- a/README
+++ b/README
@@ -22,7 +22,7 @@
     "pub  1312G/FF3EAA0B 1998-02-09 Werner Koch <wk@isil.d.shuttle.de>"
     "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 <werner.koch@guug.de>"
     "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 d0c53d5..7c04f6a 100644 (file)
--- 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 e6cf8a7..2af0c45 100644 (file)
--- 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.
       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
+
+
index 04236b7..d09871e 100644 (file)
@@ -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)
 -------------
index 3cc3b24..9886310 100644 (file)
@@ -130,8 +130,6 @@ B<--edit-key> I<name>
        Remove a subkey.
     B<passwd>
        Change the passphrase of the secret key.
-    B<check>
-       Check signatures
     B<uid> I<n>
        Toggle selection of user id with index I<n>.
        Use 0 to deselect all.
@@ -140,6 +138,8 @@ B<--edit-key> I<name>
        Use 0 to deselect all.
     B<check>
        Check all selected user ids.
+    B<pref>
+       List preferences.
     B<toggle>
        Toggle between public and secret key listing.
     B<save>
@@ -316,7 +316,8 @@ B<--marginals-needed> I<n>
 B<--cipher-algo> I<name>
     Use I<name> 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<name>
     Use I<name> as message digest algorithm. Running the
@@ -329,6 +330,8 @@ B<--compress-algo> I<number>
     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<n>
     Read the passphrase from file descriptor I<n>. If you use
index 39e528d..a907239 100644 (file)
@@ -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.
index c7ed8fa..1ddb420 100644 (file)
@@ -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 );
index 969e9af..142a5e2 100644 (file)
@@ -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: ",
index 14a4665..e6b2281 100644 (file)
@@ -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 )
index 54dc39c..acc5bf6 100644 (file)
--- 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);
 
index 912c919..72bb3d9 100644 (file)
@@ -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 */
index 85ab88b..2d3f61f 100644 (file)
@@ -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 );
index f61916b..69685bf 100644 (file)
@@ -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 );
            }
        }
     }
index 4ff81b7..7780abf 100644 (file)
@@ -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 ) {
index e7dabf5..ccc5296 100644 (file)
@@ -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));
index 630e43f..862ed41 100644 (file)
@@ -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 */
index 6a35cd8..495e722 100644 (file)
@@ -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 );
index 60e0042..396486f 100644 (file)
@@ -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);
+               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 )
-                   printf(  "[encrypted]\n");
-               else {
-                   mpi_print(stdout, sk->skey[i], mpi_print_mode  );
-                   putchar('\n');
+                   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 {
index ad8ca76..f0e2f25 100644 (file)
@@ -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 );
index dbbcbbd..4e58f12 100644 (file)
@@ -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;
+}
+
+
index 90cd260..98ad2d3 100644 (file)
@@ -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);
index 6bffb78..679d029 100644 (file)
@@ -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 );
        }
index 2aa9468..a5034c7 100644 (file)
@@ -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 ) {
index be831b3..c491329 100644 (file)
@@ -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 );
 }
index 744f98d..8660613 100644 (file)
@@ -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));
index 381d0b2..034e092 100644 (file)
@@ -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:
index 6fb0e54..0cbb851 100644 (file)
 #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;
index d1f0fd0..cc94ad8 100644 (file)
@@ -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;
index 3f24cd5..fc47007 100644 (file)
 #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 );
index 6e0e42e..d4cb56c 100644 (file)
@@ -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 );
index babbabd..3fc0b33 100644 (file)
@@ -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.
index eba82a2..2775f5b 100644 (file)
@@ -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.
index c9af505..f2f1726 100644 (file)
@@ -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 );
index 3f56669..5d8e019 100644 (file)
@@ -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 );
index aa9afe6..ece0734 100644 (file)
@@ -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.
index 3067ac4..6ad0013 100644 (file)
@@ -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");
index 583c962..d78fabe 100644 (file)
@@ -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));