summaryrefslogtreecommitdiffstats
path: root/g10
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 /g10
parentadd coprocess facility (diff)
downloadgnupg2-9b609091ab3249a41c3a9f2417ba0250405792c8.tar.xz
gnupg2-9b609091ab3249a41c3a9f2417ba0250405792c8.zip
intermediate check in
Diffstat (limited to 'g10')
-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
24 files changed, 656 insertions, 151 deletions
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 );