summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>1998-08-05 18:51:59 +0200
committerWerner Koch <wk@gnupg.org>1998-08-05 18:51:59 +0200
commit9b609091ab3249a41c3a9f2417ba0250405792c8 (patch)
treeeac3b271488722262dd71f003641d88d35fb64a1
parentadd coprocess facility (diff)
downloadgnupg2-9b609091ab3249a41c3a9f2417ba0250405792c8.tar.xz
gnupg2-9b609091ab3249a41c3a9f2417ba0250405792c8.zip
intermediate check in
-rw-r--r--NEWS5
-rw-r--r--README5
-rw-r--r--THANKS1
-rw-r--r--TODO17
-rw-r--r--doc/DETAILS1
-rw-r--r--doc/gpg.1pod9
-rw-r--r--g10/ChangeLog24
-rw-r--r--g10/build-packet.c26
-rw-r--r--g10/encode.c35
-rw-r--r--g10/free-packet.c21
-rw-r--r--g10/g10.c34
-rw-r--r--g10/getkey.c14
-rw-r--r--g10/keydb.h1
-rw-r--r--g10/keyedit.c85
-rw-r--r--g10/keygen.c35
-rw-r--r--g10/mainproc.c13
-rw-r--r--g10/options.h1
-rw-r--r--g10/packet.h6
-rw-r--r--g10/parse-packet.c108
-rw-r--r--g10/passphrase.c2
-rw-r--r--g10/pkclist.c99
-rw-r--r--g10/pubkey-enc.c15
-rw-r--r--g10/seckey-cert.c86
-rw-r--r--g10/sign.c34
-rw-r--r--g10/signal.c3
-rw-r--r--g10/status.c3
-rw-r--r--g10/tdbio.c15
-rw-r--r--g10/tdbio.h8
-rw-r--r--g10/trustdb.c132
-rw-r--r--g10/trustdb.h7
-rw-r--r--include/mpi.h5
-rw-r--r--mpi/ChangeLog9
-rw-r--r--mpi/mpicoder.c44
-rw-r--r--mpi/mpiutil.c65
-rw-r--r--tools/shmtest.c9
-rw-r--r--util/ChangeLog4
-rw-r--r--util/iobuf.c2
-rw-r--r--util/secmem.c7
38 files changed, 811 insertions, 179 deletions
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 <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 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<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
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);
+ 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 {
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));