1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-04-12 22:11:29 +02:00

intermediate check in

This commit is contained in:
Werner Koch 1998-08-05 16:51:59 +00:00
parent 6fbee8ab86
commit 9b609091ab
38 changed files with 812 additions and 180 deletions

5
NEWS
View File

@ -35,11 +35,16 @@ Noteworthy changes in version 0.3.3
* gpg now disables core dumps. * 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. * We have added the Twofish as an experimental cipher algorithm.
Many thanks to Matthew Skala for doing this work. Many thanks to Matthew Skala for doing this work.
Twofish is the AES submission from Schneier et al.; see Twofish is the AES submission from Schneier et al.; see
"www.counterpane.com/twofish.html" for more information. "www.counterpane.com/twofish.html" for more information.
* [talk about --emulate-encr-mpi-bug]
Noteworthy changes in version 0.3.2 Noteworthy changes in version 0.3.2

5
README
View File

@ -22,7 +22,7 @@
"pub 1312G/FF3EAA0B 1998-02-09 Werner Koch <wk@isil.d.shuttle.de>" "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" "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>" "pub 1024D/621CC013 1998-07-07 Werner Koch <werner.koch@guug.de>"
"Key fingerprint = ECAF 7590 EB34 43B5 C7CF 3ACB 6C7E E1B8 621C C013" "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 IDEA (which is patented worldwide) and RSA (which is patented in
the United States until Sep 20, 2000). 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 The default algorithms are now DSA and ELGamal. ELGamal for signing
is still available, but due to the larger size of such signatures it is still available, but due to the larger size of such signatures it

1
THANKS
View File

@ -29,6 +29,7 @@ Nicolas Graner Nicolas.Graner@cri.u-psud.fr
Oskari Jääskeläinen f33003a@cc.hut.fi Oskari Jääskeläinen f33003a@cc.hut.fi
Peter Gutmann pgut001@cs.auckland.ac.nz Peter Gutmann pgut001@cs.auckland.ac.nz
Ralph Gillen gillen@theochem.uni-duesseldorf.de Ralph Gillen gillen@theochem.uni-duesseldorf.de
Serge Munhoven munhoven@mema.ucl.ac.be
Steffen Ullrich ccrlphr@xensei.com Steffen Ullrich ccrlphr@xensei.com
Thomas Roessler roessler@guug.de Thomas Roessler roessler@guug.de
Tom Spindler dogcow@home.merit.edu Tom Spindler dogcow@home.merit.edu

17
TODO
View File

@ -1,5 +1,7 @@
* Fix Oscaris problems with the trustdb. * 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) * add test cases for invalid data (scrambled armor or other random data)
* fix the expire stuff for v4 packets. * fix the expire stuff for v4 packets.
@ -8,14 +10,16 @@
sig) into a compressed packet - or should we only compress the data? sig) into a compressed packet - or should we only compress the data?
what does pgp 5 do, what does OpenPGP say= 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 * 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? * 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. * 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 * Burn the buffers used by fopen(), or use read(2). Does this
really make sense? really make sense?
* enable a SIGSEGV handler while using zlib functions
* Change the buffering to a mbuf like scheme? Need it for PSST anyway. * Change the buffering to a mbuf like scheme? Need it for PSST anyway.
* add checking of armor trailers * add checking of armor trailers
* remove all "Fixmes" * remove all "Fixmes"
@ -40,3 +42,8 @@
* replace getkey.c#enum_secret_keys * replace getkey.c#enum_secret_keys
* OpenBSD has sometimes problems reading from /dev/random.
* change the fake_data stuff to mpi_set_opaque

View File

@ -128,6 +128,7 @@ Record type 5: (pref record)
1 u32 LID; points to the directory record (and not to the uid record!). 1 u32 LID; points to the directory record (and not to the uid record!).
(or 0 for standard preference record) (or 0 for standard preference record)
1 u32 next 1 u32 next
30 byte preference data
Record type 6 (sigrec) Record type 6 (sigrec)
------------- -------------

View File

@ -130,8 +130,6 @@ B<--edit-key> I<name>
Remove a subkey. Remove a subkey.
B<passwd> B<passwd>
Change the passphrase of the secret key. Change the passphrase of the secret key.
B<check>
Check signatures
B<uid> I<n> B<uid> I<n>
Toggle selection of user id with index I<n>. Toggle selection of user id with index I<n>.
Use 0 to deselect all. Use 0 to deselect all.
@ -140,6 +138,8 @@ B<--edit-key> I<name>
Use 0 to deselect all. Use 0 to deselect all.
B<check> B<check>
Check all selected user ids. Check all selected user ids.
B<pref>
List preferences.
B<toggle> B<toggle>
Toggle between public and secret key listing. Toggle between public and secret key listing.
B<save> B<save>
@ -316,7 +316,8 @@ B<--marginals-needed> I<n>
B<--cipher-algo> I<name> B<--cipher-algo> I<name>
Use I<name> as cipher algorithm. Running the program Use I<name> as cipher algorithm. Running the program
with the option B<--verbose> yields a list of supported 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> B<--digest-algo> I<name>
Use I<name> as message digest algorithm. Running the 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 version which is used by PGP. This is only used for
new messages. The default algorithm may give better new messages. The default algorithm may give better
results because the window size is not limited to 8K. 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> B<--passphrase-fd> I<n>
Read the passphrase from file descriptor I<n>. If you use Read the passphrase from file descriptor I<n>. If you use

View File

@ -1,3 +1,27 @@
Wed Aug 5 11:54:37 1998 Werner Koch (wk@(none))
* g10.c (check_opts): Moved to main. Changed def_cipher_algo
semantics and chnaged all users.
* pubkey-enc.c (get_sssion_key): New informational output
about preferences.
* parse-packet.c (parse_symkeyenc): Fixed salted+iterated S2K
(parse_key): Ditto.
* build-packet.c (do_secret_key): Ditto.
(do_symkey_enc): Ditto.
Tue Aug 4 08:59:10 1998 Werner Koch (wk@(none))
* getkey.c (enum_secret_keys): Now returns only primary keys.
* getkey (lookup): Now sets the new namehash field.
* parse-packet.c (parse_sig_subpkt2): New.
* sign.c (sign_file): one-pass sigs are now emiited reverse.
Preference data is considered when selecting the compress algo.
Wed Jul 29 12:53:03 1998 Werner Koch (wk@(none)) Wed Jul 29 12:53:03 1998 Werner Koch (wk@(none))
* free-packet.c (copy_signature): New. * free-packet.c (copy_signature): New.

View File

@ -301,18 +301,24 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
iobuf_put(a, sk->protect.s2k.mode ); iobuf_put(a, sk->protect.s2k.mode );
iobuf_put(a, sk->protect.s2k.hash_algo ); iobuf_put(a, sk->protect.s2k.hash_algo );
if( sk->protect.s2k.mode == 1 if( sk->protect.s2k.mode == 1
|| sk->protect.s2k.mode == 4 ) || sk->protect.s2k.mode == 3 )
iobuf_write(a, sk->protect.s2k.salt, 8 ); iobuf_write(a, sk->protect.s2k.salt, 8 );
if( sk->protect.s2k.mode == 4 ) if( sk->protect.s2k.mode == 3 )
write_32(a, sk->protect.s2k.count ); iobuf_put(a, sk->protect.s2k.count );
iobuf_write(a, sk->protect.iv, 8 ); iobuf_write(a, sk->protect.iv, 8 );
} }
} }
else else
iobuf_put(a, 0 ); iobuf_put(a, 0 );
for( ; i < nskey; i++ ) if( sk->is_protected && sk->version >= 4
mpi_write(a, sk->skey[i] ); && !(opt.emulate_bugs & EMUBUG_ENCR_MPI) ) {
write_16(a, sk->csum ); BUG();
}
else {
for( ; i < nskey; i++ )
mpi_write(a, sk->skey[i] );
write_16(a, sk->csum );
}
leave: leave:
write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes, 1 ); 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 ); assert( enc->version == 4 );
switch( enc->s2k.mode ) { 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 ); default: log_bug("do_symkey_enc: s2k=%d\n", enc->s2k.mode );
} }
iobuf_put( a, enc->version ); iobuf_put( a, enc->version );
iobuf_put( a, enc->cipher_algo ); iobuf_put( a, enc->cipher_algo );
iobuf_put( a, enc->s2k.mode ); iobuf_put( a, enc->s2k.mode );
iobuf_put( a, enc->s2k.hash_algo ); 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 ); iobuf_write(a, enc->s2k.salt, 8 );
if( enc->s2k.mode == 4 ) if( enc->s2k.mode == 3 )
write_32(a, enc->s2k.count); iobuf_put(a, enc->s2k.count);
} }
if( enc->seskeylen ) if( enc->seskeylen )
iobuf_write(a, enc->seskey, enc->seskeylen ); iobuf_write(a, enc->seskey, enc->seskeylen );

View File

@ -34,6 +34,7 @@
#include "util.h" #include "util.h"
#include "main.h" #include "main.h"
#include "filter.h" #include "filter.h"
#include "trustdb.h"
#include "i18n.h" #include "i18n.h"
@ -93,7 +94,9 @@ encode_simple( const char *filename, int mode )
s2k->mode = opt.rfc1991? 0:1; s2k->mode = opt.rfc1991? 0:1;
s2k->hash_algo = opt.def_digest_algo ? opt.def_digest_algo s2k->hash_algo = opt.def_digest_algo ? opt.def_digest_algo
: DEFAULT_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 ) { if( !cfx.dek || !cfx.dek->keylen ) {
rc = G10ERR_PASSPHRASE; rc = G10ERR_PASSPHRASE;
m_free(cfx.dek); m_free(cfx.dek);
@ -218,7 +221,13 @@ encode_crypt( const char *filename, STRLIST remusr )
/* create a session key */ /* create a session key */
cfx.dek = m_alloc_secure( sizeof *cfx.dek ); 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 ); make_session_key( cfx.dek );
if( DBG_CIPHER ) if( DBG_CIPHER )
log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen ); 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 */ /* register the cipher filter */
iobuf_push_filter( out, cipher_filter, &cfx ); iobuf_push_filter( out, cipher_filter, &cfx );
/* register the compress filter */ /* register the compress filter */
if( opt.compress ) if( opt.compress ) {
iobuf_push_filter( out, compress_filter, &zfx ); 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 */ /* do the work */
if( (rc = build_packet( out, &pkt )) ) if( (rc = build_packet( out, &pkt )) )
@ -293,7 +310,15 @@ encrypt_filter( void *opaque, int control,
else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */ else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
if( !efx->header_okay ) { if( !efx->header_okay ) {
efx->cfx.dek = m_alloc_secure( sizeof *efx->cfx.dek ); 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 ); make_session_key( efx->cfx.dek );
if( DBG_CIPHER ) if( DBG_CIPHER )
log_hexdump("DEK is: ", log_hexdump("DEK is: ",

View File

@ -30,6 +30,7 @@
#include "util.h" #include "util.h"
#include "cipher.h" #include "cipher.h"
#include "memory.h" #include "memory.h"
#include "options.h"
void void
free_symkey_enc( PKT_symkey_enc *enc ) free_symkey_enc( PKT_symkey_enc *enc )
@ -82,6 +83,10 @@ release_public_key_parts( PKT_public_key *pk )
mpi_free( pk->pkey[i] ); mpi_free( pk->pkey[i] );
pk->pkey[i] = NULL; 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 * 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; int n, i;
if( !d ) if( !d )
d = m_alloc(sizeof *d); d = m_alloc(sizeof *d);
memcpy( d, s, 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 ); n = pubkey_get_npkey( s->pubkey_algo );
if( !n ) if( !n )
d->pkey[0] = cp_fake_data(s->pkey[0]); 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; 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 * PKT_signature *
copy_signature( PKT_signature *d, PKT_signature *s ) copy_signature( PKT_signature *d, PKT_signature *s )

View File

@ -173,6 +173,7 @@ static ARGPARSE_OPTS opts[] = {
{ 559, "always-trust", 0, "@"}, { 559, "always-trust", 0, "@"},
{ 562, "emulate-checksum-bug", 0, "@"}, { 562, "emulate-checksum-bug", 0, "@"},
{ 554, "run-as-shm-coprocess", 4, "@" }, { 554, "run-as-shm-coprocess", 4, "@" },
{ 568, "emulate-encr-mpi-bug", 0, "@"},
{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 int
main( int argc, char **argv ) main( int argc, char **argv )
{ {
@ -426,7 +409,7 @@ main( int argc, char **argv )
i18n_init(); i18n_init();
opt.compress = -1; /* defaults to standard compress level */ opt.compress = -1; /* defaults to standard compress level */
/* fixme: set the next two to zero and decide where used */ /* 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_digest_algo = 0;
opt.def_compress_algo = 2; opt.def_compress_algo = 2;
opt.completes_needed = 1; opt.completes_needed = 1;
@ -615,6 +598,7 @@ main( int argc, char **argv )
log_error("shared memory coprocessing is not available\n"); log_error("shared memory coprocessing is not available\n");
#endif #endif
break; break;
case 568: opt.emulate_bugs |= EMUBUG_ENCR_MPI; break;
default : errors++; pargs.err = configfp? 1:2; break; default : errors++; pargs.err = configfp? 1:2; break;
} }
} }
@ -657,12 +641,22 @@ main( int argc, char **argv )
if( def_cipher_string ) { if( def_cipher_string ) {
opt.def_cipher_algo = string_to_cipher_algo(def_cipher_string); opt.def_cipher_algo = string_to_cipher_algo(def_cipher_string);
m_free(def_cipher_string); def_cipher_string = NULL; 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 ) { if( def_digest_string ) {
opt.def_digest_algo = string_to_digest_algo(def_digest_string); opt.def_digest_algo = string_to_digest_algo(def_digest_string);
m_free(def_digest_string); def_digest_string = NULL; 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) ) if( log_get_errorcount(0) )
g10_exit(2); g10_exit(2);

View File

@ -685,6 +685,8 @@ lookup( PKT_public_key *pk, int mode, u32 *keyid,
KBNODE keyblock = NULL; KBNODE keyblock = NULL;
KBPOS kbpos; KBPOS kbpos;
int oldmode = set_packet_list_mode(0); int oldmode = set_packet_list_mode(0);
byte namehash[20];
int use_namehash=0;
rc = enum_keyblocks( 0, &kbpos, &keyblock ); rc = enum_keyblocks( 0, &kbpos, &keyblock );
if( rc ) { if( rc ) {
@ -719,6 +721,10 @@ lookup( PKT_public_key *pk, int mode, u32 *keyid,
u32 aki[2]; u32 aki[2];
keyid_from_pk( kk->pkt->pkt.public_key, aki ); keyid_from_pk( kk->pkt->pkt.public_key, aki );
cache_user_id( k->pkt->pkt.user_id, 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; k = kk;
break; break;
} }
@ -799,7 +805,8 @@ lookup( PKT_public_key *pk, int mode, u32 *keyid,
if( k ) { /* found */ if( k ) { /* found */
assert( k->pkt->pkttype == PKT_PUBLIC_KEY assert( k->pkt->pkttype == PKT_PUBLIC_KEY
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY ); || 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 ); add_stuff_from_selfsig( keyblock, k );
if( ret_keyblock ) { if( ret_keyblock ) {
*ret_keyblock = 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 * 1) create a void pointer and initialize it to NULL
* 2) pass this void pointer by reference to this function * 2) pass this void pointer by reference to this function
* and provide space for the secret key (pass a buffer for sk) * 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 ) { while( (rc=parse_packet(c->iobuf, &pkt)) != -1 ) {
if( rc ) if( rc )
; /* e.g. unknown packet */ ; /* e.g. unknown packet */
else if( pkt.pkttype == PKT_SECRET_KEY else if( pkt.pkttype == PKT_SECRET_KEY ) {
|| pkt.pkttype == PKT_SECRET_SUBKEY ) {
copy_secret_key( sk, pkt.pkt.secret_key ); copy_secret_key( sk, pkt.pkt.secret_key );
set_packet_list_mode(save_mode); set_packet_list_mode(save_mode);
return 0; /* found */ return 0; /* found */

View File

@ -91,6 +91,7 @@ struct pubkey_find_info {
int check_signatures_trust( PKT_signature *sig ); int check_signatures_trust( PKT_signature *sig );
void release_pk_list( PK_LIST pk_list ); void release_pk_list( PK_LIST pk_list );
int build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned usage ); 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 --*/ /*-- skclist.c --*/
void release_sk_list( SK_LIST sk_list ); void release_sk_list( SK_LIST sk_list );

View File

@ -40,8 +40,9 @@
#include "status.h" #include "status.h"
#include "i18n.h" #include "i18n.h"
static void show_prefs( KBNODE keyblock, PKT_user_id *uid );
static void show_key_with_all_names( KBNODE keyblock, 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_key_and_fingerprint( KBNODE keyblock );
static void show_fingerprint( PKT_public_key *pk ); static void show_fingerprint( PKT_public_key *pk );
static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock ); 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) */ /* Ask whether we realy should sign these user id(s) */
tty_printf("\n"); 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("\n");
tty_printf(_( tty_printf(_(
"Are you really sure that you want to sign this key\n" "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, enum cmdids { cmdNONE = 0,
cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN, cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN,
cmdDEBUG, cmdSAVE, cmdADDUID, cmdDELUID, cmdADDKEY, cmdDELKEY, cmdDEBUG, cmdSAVE, cmdADDUID, cmdDELUID, cmdADDKEY, cmdDELKEY,
cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF,
cmdNOP }; cmdNOP };
static struct { const char *name; static struct { const char *name;
enum cmdids id; enum cmdids id;
@ -573,6 +574,7 @@ keyedit_menu( const char *username, STRLIST locusr )
{ N_("toggle") , cmdTOGGLE , 1, N_("toggle between secret " { N_("toggle") , cmdTOGGLE , 1, N_("toggle between secret "
"and public key listing") }, "and public key listing") },
{ N_("t" ) , cmdTOGGLE , 1, NULL }, { N_("t" ) , cmdTOGGLE , 1, NULL },
{ N_("pref") , cmdPREF , 0, N_("list preferences") },
{ N_("passwd") , cmdPASSWD , 1, N_("change the passphrase") }, { N_("passwd") , cmdPASSWD , 1, N_("change the passphrase") },
{ N_("trust") , cmdTRUST , 0, N_("change the ownertrust") }, { N_("trust") , cmdTRUST , 0, N_("change the ownertrust") },
@ -625,7 +627,7 @@ keyedit_menu( const char *username, STRLIST locusr )
tty_printf("\n"); tty_printf("\n");
if( redisplay ) { 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"); tty_printf("\n");
redisplay = 0; redisplay = 0;
} }
@ -670,7 +672,7 @@ keyedit_menu( const char *username, STRLIST locusr )
break; break;
case cmdQUIT: case cmdQUIT:
if( !modified ) if( !modified && !sec_modified )
goto leave; goto leave;
if( !cpr_get_answer_is_yes("keyedit.save",_("Save changes? ")) ) { if( !cpr_get_answer_is_yes("keyedit.save",_("Save changes? ")) ) {
if( cpr_enabled() if( cpr_enabled()
@ -680,11 +682,13 @@ keyedit_menu( const char *username, STRLIST locusr )
} }
/* fall thru */ /* fall thru */
case cmdSAVE: case cmdSAVE:
if( modified ) { if( modified || sec_modified ) {
rc = update_keyblock( &keyblockpos, keyblock ); if( modified ) {
if( rc ) { rc = update_keyblock( &keyblockpos, keyblock );
log_error(_("update failed: %s\n"), g10_errstr(rc) ); if( rc ) {
break; log_error(_("update failed: %s\n"), g10_errstr(rc) );
break;
}
} }
if( sec_modified ) { if( sec_modified ) {
rc = update_keyblock( &sec_keyblockpos, sec_keyblock ); rc = update_keyblock( &sec_keyblockpos, sec_keyblock );
@ -807,7 +811,7 @@ keyedit_menu( const char *username, STRLIST locusr )
break; break;
case cmdTRUST: case cmdTRUST:
show_key_with_all_names( keyblock, 0, 0, 1 ); show_key_with_all_names( keyblock, 0, 0, 1, 0 );
tty_printf("\n"); tty_printf("\n");
if( edit_ownertrust( find_kbnode( keyblock, if( edit_ownertrust( find_kbnode( keyblock,
PKT_PUBLIC_KEY )->pkt->pkt.public_key->local_id, 1 ) ) PKT_PUBLIC_KEY )->pkt->pkt.public_key->local_id, 1 ) )
@ -816,6 +820,10 @@ keyedit_menu( const char *username, STRLIST locusr )
* are updated immediately */ * are updated immediately */
break; break;
case cmdPREF:
show_key_with_all_names( keyblock, 0, 0, 0, 1 );
break;
case cmdNOP: case cmdNOP:
break; 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 * 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 static void
show_key_with_all_names( KBNODE keyblock, int only_marked, 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; KBNODE node;
int i; int i;
@ -850,6 +897,15 @@ show_key_with_all_names( KBNODE keyblock, int only_marked,
if( node->pkt->pkttype == PKT_PUBLIC_KEY if( node->pkt->pkttype == PKT_PUBLIC_KEY
|| (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) { || (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) {
PKT_public_key *pk = node->pkt->pkt.public_key; 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", tty_printf("%s%c %4u%c/%08lX created: %s expires: %s",
node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub", node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
(node->flag & NODFLG_SELKEY)? '*':' ', (node->flag & NODFLG_SELKEY)? '*':' ',
@ -859,9 +915,6 @@ show_key_with_all_names( KBNODE keyblock, int only_marked,
datestr_from_pk(pk), datestr_from_pk(pk),
expirestr_from_pk(pk) ); expirestr_from_pk(pk) );
if( node->pkt->pkttype == PKT_PUBLIC_KEY ) { 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 ); tty_printf(" trust: %c/%c", otrust, trust );
if( with_fpr ) if( with_fpr )
show_fingerprint( pk ); show_fingerprint( pk );
@ -896,6 +949,8 @@ show_key_with_all_names( KBNODE keyblock, int only_marked,
tty_printf("(%d) ", i); tty_printf("(%d) ", i);
tty_print_string( uid->name, uid->len ); tty_print_string( uid->name, uid->len );
tty_printf("\n"); tty_printf("\n");
if( with_prefs )
show_prefs( keyblock, uid );
} }
} }
} }

View File

@ -32,6 +32,7 @@
#include "ttyio.h" #include "ttyio.h"
#include "options.h" #include "options.h"
#include "keydb.h" #include "keydb.h"
#include "status.h"
#include "i18n.h" #include "i18n.h"
@ -389,7 +390,7 @@ ask_algo( int *ret_v4, int addmode )
*ret_v4 = 1; *ret_v4 = 1;
for(;;) { for(;;) {
answer = tty_get(_("Your selection? ")); answer = cpr_get("keygen.algo",_("Your selection? "));
tty_kill_prompt(); tty_kill_prompt();
algo = *answer? atoi(answer): 1; algo = *answer? atoi(answer): 1;
m_free(answer); m_free(answer);
@ -433,7 +434,7 @@ ask_keysize( int algo )
" highest suggested keysize is 2048 bits\n"), " highest suggested keysize is 2048 bits\n"),
pubkey_algo_to_string(algo) ); pubkey_algo_to_string(algo) );
for(;;) { for(;;) {
answer = tty_get(_("What keysize do you want? (1024) ")); answer = cpr_get("keygen.size",_("What keysize do you want? (1024) "));
tty_kill_prompt(); tty_kill_prompt();
nbits = *answer? atoi(answer): 1024; nbits = *answer? atoi(answer): 1024;
m_free(answer); m_free(answer);
@ -441,7 +442,7 @@ ask_keysize( int algo )
tty_printf(_("DSA only allows keysizes from 512 to 1024\n")); tty_printf(_("DSA only allows keysizes from 512 to 1024\n"));
else if( nbits < 768 ) else if( nbits < 768 )
tty_printf(_("keysize too small; 768 is smallest value allowed.\n")); 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 " tty_printf(_("Keysizes larger than 2048 are not suggested because "
"computations take REALLY long!\n")); "computations take REALLY long!\n"));
if( tty_get_answer_is_yes(_( if( tty_get_answer_is_yes(_(
@ -452,7 +453,7 @@ ask_keysize( int algo )
break; break;
} }
} }
else if( nbits > 1536 ) { else if( nbits > 1536 && !cpr_enabled() ) {
if( tty_get_answer_is_yes(_( if( tty_get_answer_is_yes(_(
"Do you really need such a large keysize? ")) ) "Do you really need such a large keysize? ")) )
break; break;
@ -494,7 +495,7 @@ ask_valid_days()
int mult; int mult;
m_free(answer); m_free(answer);
answer = tty_get(_("Key is valid for? (0) ")); answer = cpr_get("keygen.valid",_("Key is valid for? (0) "));
tty_kill_prompt(); tty_kill_prompt();
trim_spaces(answer); trim_spaces(answer);
if( !*answer ) if( !*answer )
@ -517,7 +518,8 @@ ask_valid_days()
add_days_to_timestamp( make_timestamp(), 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; break;
} }
m_free(answer); m_free(answer);
@ -556,7 +558,7 @@ ask_user_id( int mode )
if( !aname ) { if( !aname ) {
for(;;) { for(;;) {
m_free(aname); m_free(aname);
aname = tty_get(_("Real name: ")); aname = cpr_get("keygen.name",_("Real name: "));
trim_spaces(aname); trim_spaces(aname);
tty_kill_prompt(); tty_kill_prompt();
if( strpbrk( aname, "<([])>" ) ) if( strpbrk( aname, "<([])>" ) )
@ -572,7 +574,7 @@ ask_user_id( int mode )
if( !amail ) { if( !amail ) {
for(;;) { for(;;) {
m_free(amail); m_free(amail);
amail = tty_get(_("Email address: ")); amail = cpr_get("keygen.email",_("Email address: "));
trim_spaces(amail); trim_spaces(amail);
strlwr(amail); strlwr(amail);
tty_kill_prompt(); tty_kill_prompt();
@ -592,7 +594,7 @@ ask_user_id( int mode )
if( !acomment ) { if( !acomment ) {
for(;;) { for(;;) {
m_free(acomment); m_free(acomment);
acomment = tty_get(_("Comment: ")); acomment = cpr_get("keygen.comment",_("Comment: "));
trim_spaces(acomment); trim_spaces(acomment);
tty_kill_prompt(); tty_kill_prompt();
if( !*acomment ) if( !*acomment )
@ -622,9 +624,16 @@ ask_user_id( int mode )
/* fixme: add a warning if this user-id already exists */ /* fixme: add a warning if this user-id already exists */
for(;;) { for(;;) {
char *ansstr = N_("NnCcEeOoQq"); char *ansstr = N_("NnCcEeOoQq");
answer = tty_get(_(
"Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? ")); if( cpr_enabled() ) {
tty_kill_prompt(); 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 ) if( strlen(answer) > 1 )
; ;
else if( *answer == ansstr[0] || *answer == ansstr[1] ) { else if( *answer == ansstr[0] || *answer == ansstr[1] ) {
@ -950,7 +959,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
assert(algo); assert(algo);
nbits = ask_keysize( algo ); nbits = ask_keysize( algo );
ndays = ask_valid_days(); ndays = ask_valid_days();
if( !tty_get_answer_is_yes( _("Really create? ") ) ) if( !cpr_enabled() && !tty_get_answer_is_yes( _("Really create? ") ) )
goto leave; goto leave;
if( passphrase ) { if( passphrase ) {

View File

@ -171,6 +171,7 @@ proc_pubkey_enc( CTX c, PACKET *pkt )
PKT_pubkey_enc *enc; PKT_pubkey_enc *enc;
int result = 0; int result = 0;
/* check whether the secret key is available and store in this case */
c->last_was_session_key = 1; c->last_was_session_key = 1;
enc = pkt->pkt.pubkey_enc; enc = pkt->pkt.pubkey_enc;
/*printf("enc: encrypted by a pubkey with keyid %08lX\n", enc->keyid[1] );*/ /*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 ");*/ /*printf("dat: %sencrypted data\n", c->dek?"":"conventional ");*/
if( !c->dek && !c->last_was_session_key ) { if( !c->dek && !c->last_was_session_key ) {
/* assume this is old conventional encrypted data */ /* 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 ) else if( !c->dek )
result = G10ERR_NO_SECKEY; result = G10ERR_NO_SECKEY;
@ -223,6 +226,8 @@ proc_encrypted( CTX c, PACKET *pkt )
} }
else { else {
log_error(_("decryption failed: %s\n"), g10_errstr(result)); log_error(_("decryption failed: %s\n"), g10_errstr(result));
/* FIXME: if this is secret key not available, try with
* other keys */
} }
free_packet(pkt); free_packet(pkt);
c->last_was_session_key = 0; c->last_was_session_key = 0;
@ -707,7 +712,9 @@ do_proc_packets( CTX c, IOBUF a )
while( (rc=parse_packet(a, pkt)) != -1 ) { while( (rc=parse_packet(a, pkt)) != -1 ) {
/* cleanup if we have an illegal data structure */ /* cleanup if we have an illegal data structure */
if( c->dek && pkt->pkttype != PKT_ENCRYPTED ) { 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 */ 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 */ /* ask for file and hash it */
if( c->sigs_only ) if( c->sigs_only )
rc = hash_datafiles( c->mfx.md, c->signed_data, c->sigfilename, 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 else
rc = ask_for_detached_datafile( &c->mfx, rc = ask_for_detached_datafile( &c->mfx,
iobuf_get_fname(c->iobuf)); iobuf_get_fname(c->iobuf));

View File

@ -56,6 +56,7 @@ struct {
#define EMUBUG_GPGCHKSUM 1 #define EMUBUG_GPGCHKSUM 1
#define EMUBUG_ENCR_MPI 2
#define DBG_PACKET_VALUE 1 /* debug packet reading/writing */ #define DBG_PACKET_VALUE 1 /* debug packet reading/writing */
#define DBG_MPI_VALUE 2 /* debug mpi details */ #define DBG_MPI_VALUE 2 /* debug mpi details */

View File

@ -112,6 +112,7 @@ typedef struct {
byte pubkey_usage; /* for now only used to pass it to getkey() */ byte pubkey_usage; /* for now only used to pass it to getkey() */
ulong local_id; /* internal use, valid if > 0 */ ulong local_id; /* internal use, valid if > 0 */
u32 keyid[2]; /* calculated by keyid_from_pk() */ u32 keyid[2]; /* calculated by keyid_from_pk() */
byte *namehash; /* if != NULL: found by this name */
MPI pkey[PUBKEY_MAX_NPKEY]; MPI pkey[PUBKEY_MAX_NPKEY];
} PKT_public_key; } 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 ); int skip_some_packets( IOBUF inp, unsigned n );
const byte *parse_sig_subpkt( const byte *buffer, const byte *parse_sig_subpkt( const byte *buffer,
sigsubpkttype_t reqtype, size_t *ret_n ); 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 --*/ /*-- build-packet.c --*/
int build_packet( IOBUF inp, PACKET *pkt ); 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_comment( PKT_comment *rem );
void free_packet( PACKET *pkt ); 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( 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_secret_key *copy_secret_key( PKT_secret_key *d, PKT_secret_key *s );
PKT_signature *copy_signature( PKT_signature *d, PKT_signature *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 ); PKT_user_id *copy_user_id( PKT_user_id *d, PKT_user_id *s );

View File

@ -461,6 +461,25 @@ read_rest( IOBUF inp, ulong *r_pktlen )
return p; 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 static int
parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) 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 */ case 1: /* salted s2k */
minlen = 8; minlen = 8;
break; break;
case 4: /* iterated+salted s2k */ case 3: /* iterated+salted s2k */
minlen = 12; minlen = 9;
break; break;
default: default:
log_error("unknown S2K %d\n", s2kmode ); 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->cipher_algo = cipher_algo;
k->s2k.mode = s2kmode; k->s2k.mode = s2kmode;
k->s2k.hash_algo = hash_algo; k->s2k.hash_algo = hash_algo;
if( s2kmode == 1 || s2kmode == 4 ) { if( s2kmode == 1 || s2kmode == 3 ) {
for(i=0; i < 8 && pktlen; i++, pktlen-- ) for(i=0; i < 8 && pktlen; i++, pktlen-- )
k->s2k.salt[i] = iobuf_get_noeof(inp); k->s2k.salt[i] = iobuf_get_noeof(inp);
} }
if( s2kmode == 4 ) { if( s2kmode == 3 ) {
k->s2k.count = read_32(inp); pktlen -= 4; k->s2k.count = iobuf_get(inp); pktlen--;
} }
k->seskeylen = seskeylen; k->seskeylen = seskeylen;
for(i=0; i < seskeylen && pktlen; i++, pktlen-- ) 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 ) { if( list_mode ) {
printf(":symkey enc packet: version %d, cipher %d, s2k %d, hash %d\n", printf(":symkey enc packet: version %d, cipher %d, s2k %d, hash %d\n",
version, cipher_algo, s2kmode, hash_algo); version, cipher_algo, s2kmode, hash_algo);
if( s2kmode == 1 || s2kmode == 4 ) { if( s2kmode == 1 || s2kmode == 3 ) {
printf("\tsalt "); printf("\tsalt ");
for(i=0; i < 8; i++ ) for(i=0; i < 8; i++ )
printf("%02x", k->s2k.salt[i]); printf("%02x", k->s2k.salt[i]);
if( s2kmode == 4 ) if( s2kmode == 3 )
printf(", count %lu\n", (ulong)k->s2k.count ); printf(", count %lu\n", (ulong)k->s2k.count );
printf("\n"); printf("\n");
} }
@ -675,6 +694,10 @@ parse_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, size_t *ret_n )
if( n < 8 ) if( n < 8 )
break; break;
return buffer; return buffer;
case SIGSUBPKT_PREF_SYM:
case SIGSUBPKT_PREF_HASH:
case SIGSUBPKT_PREF_COMPR:
return buffer;
case SIGSUBPKT_PRIV_ADD_SIG: case SIGSUBPKT_PRIV_ADD_SIG:
/* because we use private data, we check the GNUPG marker */ /* because we use private data, we check the GNUPG marker */
if( n < 24 ) 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 static int
parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
PKT_signature *sig ) PKT_signature *sig )
@ -779,7 +815,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
log_error("signature packet without timestamp\n"); log_error("signature packet without timestamp\n");
else else
sig->timestamp = buffer_to_u32(p); 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 ) if( !p )
log_error("signature packet without keyid\n"); log_error("signature packet without keyid\n");
else { 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; PKT_secret_key *sk = pkt->pkt.secret_key;
byte temp[8]; 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--; sk->protect.s2k.hash_algo = iobuf_get_noeof(inp); pktlen--;
switch( sk->protect.s2k.mode ) { switch( sk->protect.s2k.mode ) {
case 1: case 1:
case 4: case 3:
for(i=0; i < 8 && pktlen; i++, pktlen-- ) for(i=0; i < 8 && pktlen; i++, pktlen-- )
temp[i] = iobuf_get_noeof(inp); temp[i] = iobuf_get_noeof(inp);
memcpy(sk->protect.s2k.salt, temp, 8 ); memcpy(sk->protect.s2k.salt, temp, 8 );
@ -1001,7 +1037,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
break; break;
case 1: if( list_mode ) printf( "\tsalted S2K" ); case 1: if( list_mode ) printf( "\tsalted S2K" );
break; break;
case 4: if( list_mode ) printf( "\titer+salt S2K" ); case 3: if( list_mode ) printf( "\titer+salt S2K" );
break; break;
default: default:
if( list_mode ) if( list_mode )
@ -1016,7 +1052,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
sk->protect.algo, sk->protect.algo,
sk->protect.s2k.hash_algo ); sk->protect.s2k.hash_algo );
if( sk->protect.s2k.mode == 1 if( sk->protect.s2k.mode == 1
|| sk->protect.s2k.mode == 4 ) { || sk->protect.s2k.mode == 3 ) {
printf(", salt: "); printf(", salt: ");
for(i=0; i < 8; i++ ) for(i=0; i < 8; i++ )
printf("%02x", sk->protect.s2k.salt[i]); printf("%02x", sk->protect.s2k.salt[i]);
@ -1024,13 +1060,13 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
putchar('\n'); putchar('\n');
} }
if( sk->protect.s2k.mode == 4 ) { if( sk->protect.s2k.mode == 3 ) {
if( pktlen < 4 ) { if( pktlen < 1 ) {
rc = G10ERR_INVALID_PACKET; rc = G10ERR_INVALID_PACKET;
goto leave; goto leave;
} }
sk->protect.s2k.count = read_32(inp); sk->protect.s2k.count = iobuf_get(inp);
pktlen -= 4; 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, * If the user is so careless, not to protect his secret key,
* we can assume, that he operates an open system :=(. * we can assume, that he operates an open system :=(.
* So we put the key into secure memory when we unprotect it. */ * So we put the key into secure memory when we unprotect it. */
if( is_v4 && sk->is_protected && !(opt.emulate_bugs & EMUBUG_ENCR_MPI)){
for(i=npkey; i < nskey; i++ ) { /* ugly; the length is encrypted too, so wee read all
n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n; * stuff up to the end of the packet into the first
if( sk->is_protected ) * skey element */
mpi_set_protect_flag(sk->skey[i]); sk->skey[npkey] = mpi_set_opaque(NULL,
read_rest2(inp, pktlen), pktlen );
pktlen = 0;
if( list_mode ) { if( list_mode ) {
printf( "\tskey[%d]: ", i); printf("\tencrypted stuff follows\n");
if( sk->is_protected )
printf( "[encrypted]\n");
else {
mpi_print(stdout, sk->skey[i], mpi_print_mode );
putchar('\n');
}
} }
} }
else { /* v3 method: the mpi length is not encrypted */
for(i=npkey; i < nskey; i++ ) {
n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
if( sk->is_protected )
mpi_set_protect_flag(sk->skey[i]);
if( list_mode ) {
printf( "\tskey[%d]: ", i);
if( sk->is_protected )
printf( "[encrypted]\n");
else {
mpi_print(stdout, sk->skey[i], mpi_print_mode );
putchar('\n');
}
}
}
sk->csum = read_16(inp); pktlen -= 2; sk->csum = read_16(inp); pktlen -= 2;
if( list_mode ) { if( list_mode ) {
printf("\tchecksum: %04hx\n", sk->csum); printf("\tchecksum: %04hx\n", sk->csum);
}
} }
} }
else { else {

View File

@ -195,7 +195,7 @@ hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create )
assert( s2k->hash_algo ); assert( s2k->hash_algo );
dek->keylen = 0; dek->keylen = 0;
md = md_open( s2k->hash_algo, 1); md = md_open( s2k->hash_algo, 1);
if( s2k->mode == 1 || s2k->mode == 4 ) { if( s2k->mode == 1 || s2k->mode == 3 ) {
if( create ) if( create )
randomize_buffer(s2k->salt, 8, 1); randomize_buffer(s2k->salt, 8, 1);
md_write( md, s2k->salt, 8 ); md_write( md, s2k->salt, 8 );

View File

@ -512,3 +512,102 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned usage )
} }
/****************
* Return -1 if we could not find an algorithm.
*/
int
select_algo_from_prefs( PK_LIST pk_list, int preftype )
{
PK_LIST pkr;
u32 bits[8];
byte *pref = NULL;
size_t npref;
int i, j;
int compr_hack=0;
int any;
if( !pk_list )
return -1;
memset( bits, ~0, 8 * sizeof *bits );
for( pkr = pk_list; pkr; pkr = pkr->next ) {
u32 mask[8];
memset( mask, 0, 8 * sizeof *mask );
if( !pkr->pk->local_id )
BUG(); /* if this occurs, we can use get_ownertrust to set it */
if( preftype == PREFTYPE_SYM )
bits[0] = (1<<2); /* 3DES is implicitly there */
m_free(pref);
pref = get_pref_data( pkr->pk->local_id, pkr->pk->namehash, &npref);
any = 0;
if( pref ) {
/*log_hexdump("raw: ", pref, npref );*/
for(i=0; i+1 < npref; i+=2 ) {
if( pref[i] == preftype ) {
mask[pref[i+1]/32] |= 1 << (pref[i+1]%32);
any = 1;
}
}
}
if( (!pref || !any) && preftype == PREFTYPE_COMPR ) {
mask[0] |= 3; /* asume no_compression and old pgp */
compr_hack = 1;
}
/*log_debug("mask=%08lX%08lX%08lX%08lX%08lX%08lX%08lX%08lX\n",
(ulong)mask[7], (ulong)mask[6], (ulong)mask[5], (ulong)mask[4],
(ulong)mask[3], (ulong)mask[2], (ulong)mask[1], (ulong)mask[0]);*/
for(i=0; i < 8; i++ )
bits[i] &= mask[i];
/*log_debug("bits=%08lX%08lX%08lX%08lX%08lX%08lX%08lX%08lX\n",
(ulong)bits[7], (ulong)bits[6], (ulong)bits[5], (ulong)bits[4],
(ulong)bits[3], (ulong)bits[2], (ulong)bits[1], (ulong)bits[0]);*/
}
/* usable algorithms are now in bits
* We now use the last key from pk_list to select
* the algorithm we want to use. there are no
* preferences for the last key, we select the one
* corresponding to first set bit.
*/
i = -1;
any = 0;
if( pref ) {
for(j=0; j+1 < npref; j+=2 ) {
if( pref[j] == preftype ) {
any = 1;
if( (bits[pref[j+1]/32] & (1<<(pref[j+1]%32))) ) {
i = pref[j+1];
break;
}
}
}
}
if( !pref || !any ) {
for(j=0; j < 256; j++ )
if( (bits[j/32] & (1<<(j%32))) ) {
i = j;
break;
}
}
/*log_debug("prefs of type %d: selected %d\n", preftype, i );*/
if( compr_hack && !i ) {
/* selected no compression, but we should check whether
* algorithm 1 is also available (the ordering is not relevant
* in this case). */
if( bits[0] & (1<<1) )
i = 1; /* yep; we can use compression algo 1 */
}
if( preftype == PREFTYPE_SYM && i == CIPHER_ALGO_3DES ) {
i = CIPHER_ALGO_BLOWFISH;
if( opt.verbose )
log_info("replacing 3DES by Blowfish\n");
}
m_free(pref);
return i;
}

View File

@ -28,6 +28,7 @@
#include "packet.h" #include "packet.h"
#include "mpi.h" #include "mpi.h"
#include "keydb.h" #include "keydb.h"
#include "trustdb.h"
#include "cipher.h" #include "cipher.h"
#include "status.h" #include "status.h"
@ -124,6 +125,20 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
} }
if( DBG_CIPHER ) if( DBG_CIPHER )
log_hexdump("DEK is:", dek->key, dek->keylen ); 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: leave:
mpi_free(plain_dek); mpi_free(plain_dek);

View File

@ -67,19 +67,48 @@ do_check( PKT_secret_key *sk )
memcpy(save_iv, sk->protect.iv, 8 ); memcpy(save_iv, sk->protect.iv, 8 );
cipher_decrypt( cipher_hd, sk->protect.iv, sk->protect.iv, 8 ); cipher_decrypt( cipher_hd, sk->protect.iv, sk->protect.iv, 8 );
csum = 0; csum = 0;
for(i=pubkey_get_npkey(sk->pubkey_algo); if( sk->version >= 4 && !(opt.emulate_bugs & EMUBUG_ENCR_MPI) ) {
i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { int ndata;
buffer = mpi_get_secure_buffer( sk->skey[i], &nbytes, NULL ); byte *p, *data;
cipher_sync( cipher_hd );
assert( mpi_is_protected(sk->skey[i]) ); i = pubkey_get_npkey(sk->pubkey_algo);
cipher_decrypt( cipher_hd, buffer, buffer, nbytes ); assert( mpi_is_opaque( sk->skey[i] ) );
mpi_set_buffer( sk->skey[i], buffer, nbytes, 0 ); p = mpi_get_opaque( sk->skey[i], &ndata );
mpi_clear_protect_flag( sk->skey[i] ); data = m_alloc_secure( ndata );
csum += checksum_mpi( sk->skey[i] ); cipher_decrypt( cipher_hd, data, p, ndata );
m_free( buffer ); 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 ) { else {
csum = sk->csum; 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 ); cipher_close( cipher_hd );
/* now let's see whether we have used the right passphrase */ /* 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_setkey( cipher_hd, dek->key, dek->keylen );
cipher_setiv( cipher_hd, NULL ); cipher_setiv( cipher_hd, NULL );
cipher_encrypt( cipher_hd, sk->protect.iv, sk->protect.iv, 8 ); cipher_encrypt( cipher_hd, sk->protect.iv, sk->protect.iv, 8 );
/* NOTE: we always recalculate the checksum because there are some if( sk->version >= 4 && !(opt.emulate_bugs & EMUBUG_ENCR_MPI) ) {
* test releases which calculated it wrong */ BUG();
csum = 0; }
for(i=pubkey_get_npkey(sk->pubkey_algo); else {
i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { /* NOTE: we always recalculate the checksum because there
csum += checksum_mpi_counted_nbits( sk->skey[i] ); * are some * test releases which calculated it wrong */
buffer = mpi_get_buffer( sk->skey[i], &nbytes, NULL ); csum = 0;
cipher_sync( cipher_hd ); for(i=pubkey_get_npkey(sk->pubkey_algo);
assert( !mpi_is_protected(sk->skey[i]) ); i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
cipher_encrypt( cipher_hd, buffer, buffer, nbytes ); csum += checksum_mpi_counted_nbits( sk->skey[i] );
mpi_set_buffer( sk->skey[i], buffer, nbytes, 0 ); buffer = mpi_get_buffer( sk->skey[i], &nbytes, NULL );
mpi_set_protect_flag( sk->skey[i] ); cipher_sync( cipher_hd );
m_free( buffer ); 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; sk->is_protected = 1;
cipher_close( cipher_hd ); cipher_close( cipher_hd );
} }

View File

@ -35,6 +35,7 @@
#include "main.h" #include "main.h"
#include "filter.h" #include "filter.h"
#include "ttyio.h" #include "ttyio.h"
#include "trustdb.h"
#include "i18n.h" #include "i18n.h"
@ -118,6 +119,8 @@ only_old_style( SK_LIST sk_list )
return old_style; return old_style;
} }
/**************** /****************
* Sign the files whose names are in FILENAME. * Sign the files whose names are in FILENAME.
* If DETACHED has the value true, * If DETACHED has the value true,
@ -150,6 +153,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
SK_LIST sk_rover = NULL; SK_LIST sk_rover = NULL;
int multifile = 0; int multifile = 0;
int old_style = opt.rfc1991; int old_style = opt.rfc1991;
int compr_algo = -1; /* unknown */
memset( &afx, 0, sizeof afx); memset( &afx, 0, sizeof afx);
@ -176,6 +180,8 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
if( encrypt ) { if( encrypt ) {
if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC )) ) if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC )) )
goto leave; goto leave;
if( !old_style )
compr_algo = select_algo_from_prefs( pk_list, PREFTYPE_COMPR );
} }
/* prepare iobufs */ /* prepare iobufs */
@ -227,16 +233,31 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
} }
if( opt.compress && !outfile && ( !detached || opt.compress_sigs) ) { if( opt.compress && !outfile && ( !detached || opt.compress_sigs) ) {
if( old_style ) if( !compr_algo )
zfx.algo = 1; ; /* don't use compression */
iobuf_push_filter( out, compress_filter, &zfx ); else {
if( old_style || compr_algo == 1 )
zfx.algo = 1;
iobuf_push_filter( out, compress_filter, &zfx );
}
} }
if( !detached && !old_style ) { if( !detached && !old_style ) {
/* loop over the secret certificates and build headers */ int skcount=0;
for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { /* 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_secret_key *sk;
PKT_onepass_sig *ops; 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; sk = sk_rover->sk;
ops = m_alloc_clear( sizeof *ops ); 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->digest_algo = hash_for(sk->pubkey_algo);
ops->pubkey_algo = sk->pubkey_algo; ops->pubkey_algo = sk->pubkey_algo;
keyid_from_sk( sk, ops->keyid ); keyid_from_sk( sk, ops->keyid );
ops->last = !sk_rover->next; ops->last = skcount == 1;
init_packet(&pkt); init_packet(&pkt);
pkt.pkttype = PKT_ONEPASS_SIG; pkt.pkttype = PKT_ONEPASS_SIG;
@ -259,7 +280,6 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
} }
} }
/* setup the inner packet */ /* setup the inner packet */
if( detached ) { if( detached ) {
if( multifile ) { if( multifile ) {

View File

@ -60,7 +60,7 @@ got_fatal_signal( int sig )
fprintf( stderr, "\n%s: %s caught ... exiting\n", fprintf( stderr, "\n%s: %s caught ... exiting\n",
log_get_name(), signal_name(sig) ); log_get_name(), signal_name(sig) );
secmem_term(); secmem_term();
exit( 2 ); exit( 8 );
} }
@ -94,6 +94,7 @@ init_signals()
do_sigaction( SIGHUP, &nact ); do_sigaction( SIGHUP, &nact );
do_sigaction( SIGTERM, &nact ); do_sigaction( SIGTERM, &nact );
do_sigaction( SIGQUIT, &nact ); do_sigaction( SIGQUIT, &nact );
do_sigaction( SIGSEGV, &nact );
nact.sa_handler = got_usr_signal; nact.sa_handler = got_usr_signal;
sigaction( SIGUSR1, &nact, NULL ); sigaction( SIGUSR1, &nact, NULL );
} }

View File

@ -113,8 +113,7 @@ init_shm_coprocessing ( ulong requested_shm_size, int lock_mem )
log_fatal("too much shared memory requested; only 8k are allowed\n"); log_fatal("too much shared memory requested; only 8k are allowed\n");
shm_size = 4096 /* one page for us */ + requested_shm_size; shm_size = 4096 /* one page for us */ + requested_shm_size;
/* FIXME: Need other permissions ... */ shm_id = shmget( IPC_PRIVATE, shm_size, IPC_CREAT | 0700 );
shm_id = shmget( IPC_PRIVATE, shm_size, IPC_CREAT | 0777 );
if ( shm_id == -1 ) if ( shm_id == -1 )
log_fatal("can't get %uk of shared memory: %s\n", log_fatal("can't get %uk of shared memory: %s\n",
(unsigned)shm_size/1024, strerror(errno)); (unsigned)shm_size/1024, strerror(errno));

View File

@ -356,6 +356,7 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
{ {
int i; int i;
ulong rnum = rec->recnum; ulong rnum = rec->recnum;
byte *p;
fprintf(fp, "rec %5lu, ", rnum ); fprintf(fp, "rec %5lu, ", rnum );
@ -405,9 +406,15 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
putc('\n', fp); putc('\n', fp);
break; break;
case RECTYPE_PREF: case RECTYPE_PREF:
fprintf(fp, "pref %lu, next=%lu\n", fprintf(fp, "pref %lu, next=%lu,",
rec->r.uid.lid, rec->r.pref.lid, rec->r.pref.next);
rec->r.uid.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; break;
case RECTYPE_SIG: case RECTYPE_SIG:
fprintf(fp, "sig %lu, next=%lu,", fprintf(fp, "sig %lu, next=%lu,",
@ -537,6 +544,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
case RECTYPE_PREF: /* preference record */ case RECTYPE_PREF: /* preference record */
rec->r.pref.lid = buftoulong(p); p += 4; rec->r.pref.lid = buftoulong(p); p += 4;
rec->r.pref.next = buftoulong(p); p += 4; rec->r.pref.next = buftoulong(p); p += 4;
memcpy( rec->r.pref.data, p, 30 );
break; break;
case RECTYPE_SIG: case RECTYPE_SIG:
rec->r.sig.lid = buftoulong(p); p += 4; rec->r.sig.lid = buftoulong(p); p += 4;
@ -638,6 +646,7 @@ tdbio_write_record( TRUSTREC *rec )
case RECTYPE_PREF: case RECTYPE_PREF:
ulongtobuf(p, rec->r.pref.lid); p += 4; ulongtobuf(p, rec->r.pref.lid); p += 4;
ulongtobuf(p, rec->r.pref.next); p += 4; ulongtobuf(p, rec->r.pref.next); p += 4;
memcpy( p, rec->r.pref.data, 30 );
break; break;
case RECTYPE_SIG: case RECTYPE_SIG:

View File

@ -26,6 +26,10 @@
#define SIGS_PER_RECORD ((TRUST_RECORD_LEN-10)/5) #define SIGS_PER_RECORD ((TRUST_RECORD_LEN-10)/5)
#define ITEMS_PER_HTBL_RECORD ((TRUST_RECORD_LEN-2)/4) #define ITEMS_PER_HTBL_RECORD ((TRUST_RECORD_LEN-2)/4)
#define ITEMS_PER_HLST_RECORD ((TRUST_RECORD_LEN-6)/5) #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 #define MAX_LIST_SIGS_DEPTH 20
@ -40,7 +44,6 @@
#define RECTYPE_HLST 11 #define RECTYPE_HLST 11
#define DIRF_CHECKED 1 /* everything has been checked, the other bits are #define DIRF_CHECKED 1 /* everything has been checked, the other bits are
valid */ valid */
#define DIRF_MISKEY 2 /* some keys are missing, so they could not be checked*/ #define DIRF_MISKEY 2 /* some keys are missing, so they could not be checked*/
@ -91,10 +94,11 @@ struct trust_record {
byte uidflags; byte uidflags;
byte namehash[20]; /* ripemd hash of the username */ byte namehash[20]; /* ripemd hash of the username */
} uid; } uid;
struct { /* preference reord */ struct { /* preference record */
ulong lid; /* point back to the directory record */ ulong lid; /* point back to the directory record */
/* or 0 for a glocal pref record */ /* or 0 for a glocal pref record */
ulong next; /* points to next pref record */ ulong next; /* points to next pref record */
byte data[ITEMS_PER_PREF_RECORD];
} pref; } pref;
struct { /* signature record */ struct { /* signature record */
ulong lid; ulong lid;

View File

@ -1593,8 +1593,6 @@ check_trust( PKT_public_key *pk, unsigned *r_trustlevel )
u32 keyid[2]; u32 keyid[2];
if( DBG_TRUST )
log_info("check_trust() called.\n");
keyid_from_pk( pk, keyid ); keyid_from_pk( pk, keyid );
/* get the pubkey record */ /* 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 * This function simply looks for the key in the trustdb
@ -1909,8 +1991,40 @@ insert_trust_record( PKT_public_key *orig_pk )
rc = 0; rc = 0;
} }
else { /* build the prefrecord */ 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);
assert(!uidlist->help_pref);
uidlist->mark |= 1; /* mark valid */ 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 */ ) { 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->r.uid.lid = dirrec.recnum;
rec->recnum = tdbio_new_recnum(); rec->recnum = tdbio_new_recnum();
/* (preference records) */ /* (preference records) */
for( rec2 = rec->help_pref; rec2; rec2 = rec2->next ) { if( rec->help_pref ) {
rec2->r.pref.lid = dirrec.recnum; for( rec2 = rec->help_pref; rec2; rec2 = rec2->next ) {
rec2->recnum = tdbio_new_recnum(); 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 ) for(rec=uidlist_head; rec; rec = rec->next )
rec->r.uid.next = rec->next? rec->next->recnum : 0; rec->r.uid.next = rec->next? rec->next->recnum : 0;

View File

@ -35,6 +35,11 @@
#define TRUST_FLAG_REVOKED 32 /* r: revoked */ #define TRUST_FLAG_REVOKED 32 /* r: revoked */
#define PREFTYPE_SYM 1
#define PREFTYPE_HASH 2
#define PREFTYPE_COMPR 3
/*-- trustdb.c --*/ /*-- trustdb.c --*/
void list_trustdb(const char *username); void list_trustdb(const char *username);
void list_trust_path( int max_depth, 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 enum_trust_web( void **context, ulong *lid );
int get_ownertrust( ulong lid, unsigned *r_otrust ); int get_ownertrust( ulong lid, unsigned *r_otrust );
int get_ownertrust_info( ulong lid ); 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 keyid_from_lid( ulong lid, u32 *keyid );
int query_trust_record( PKT_public_key *pk ); int query_trust_record( PKT_public_key *pk );
int insert_trust_record( PKT_public_key *pk ); int insert_trust_record( PKT_public_key *pk );

View File

@ -50,6 +50,7 @@ typedef struct mpi_struct {
int sign; /* indicates a negative number */ int sign; /* indicates a negative number */
unsigned flags; /* bit 0: array must be allocated in secure memory space */ unsigned flags; /* bit 0: array must be allocated in secure memory space */
/* bit 1: the mpi is encrypted */ /* 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_limb_t *d; /* array with the limbs */
} *MPI; } *MPI;
@ -80,6 +81,9 @@ typedef struct mpi_struct {
void mpi_resize( MPI a, unsigned nlimbs ); void mpi_resize( MPI a, unsigned nlimbs );
MPI mpi_copy( MPI a ); MPI mpi_copy( MPI a );
#endif #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_is_protected(a) ((a) && ((a)->flags&2))
#define mpi_set_protect_flag(a) ((a)->flags |= 2) #define mpi_set_protect_flag(a) ((a)->flags |= 2)
#define mpi_clear_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 #else
MPI mpi_read(IOBUF inp, unsigned *nread, int secure); MPI mpi_read(IOBUF inp, unsigned *nread, int secure);
#endif #endif
MPI mpi_read_from_buffer(byte *buffer, unsigned *ret_nread, int secure);
int mpi_fromstr(MPI val, const char *str); int mpi_fromstr(MPI val, const char *str);
int mpi_print( FILE *fp, MPI a, int mode ); int mpi_print( FILE *fp, MPI a, int mode );
u32 mpi_get_keyid( MPI a, u32 *keyid ); u32 mpi_get_keyid( MPI a, u32 *keyid );

View File

@ -1,3 +1,12 @@
Wed Aug 5 15:11:12 1998 Werner Koch (wk@(none))
* mpicoder.c (mpi_read_from_buffer): New.
* mpiutil.c (mpi_set_opaque): New.
(mpi_get_opaque): New.
(mpi_copy): Changed to support opauqe flag
(mpi_free): Ditto.
Sat Jul 4 10:11:11 1998 Werner Koch (wk@isil.d.shuttle.de) Sat Jul 4 10:11:11 1998 Werner Koch (wk@isil.d.shuttle.de)
* mpiutil.c (mpi_clear): Reset flags. * mpiutil.c (mpi_clear): Reset flags.

View File

@ -123,6 +123,50 @@ mpi_read(IOBUF inp, unsigned *ret_nread, int secure)
} }
MPI
mpi_read_from_buffer(byte *buffer, unsigned *ret_nread, int secure)
{
int i, j;
unsigned nbits, nbytes, nlimbs, nread=0;
mpi_limb_t a;
MPI val = MPI_NULL;
if( *ret_nread < 2 )
goto leave;
nbits = buffer[0] << 8 | buffer[1];
if( nbits > MAX_EXTERN_MPI_BITS ) {
log_error("mpi too large (%u bits)\n", nbits);
goto leave;
}
buffer += 2;
nread = 2;
nbytes = (nbits+7) / 8;
nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
val = secure? mpi_alloc_secure( nlimbs )
: mpi_alloc( nlimbs );
i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
i %= BYTES_PER_MPI_LIMB;
val->nbits = nbits;
j= val->nlimbs = nlimbs;
val->sign = 0;
for( ; j > 0; j-- ) {
a = 0;
for(; i < BYTES_PER_MPI_LIMB; i++ ) {
if( ++nread > *ret_nread )
log_bug("mpi larger than buffer");
a <<= 8;
a |= *buffer++;
}
i = 0;
val->d[j-1] = a;
}
leave:
*ret_nread = nread;
return val;
}
/**************** /****************
* Make an mpi from a character string. * Make an mpi from a character string.

View File

@ -193,12 +193,16 @@ mpi_free( MPI a )
return; return;
if( DBG_MEMORY ) if( DBG_MEMORY )
log_debug("mpi_free\n" ); log_debug("mpi_free\n" );
#ifdef M_DEBUG if( a->flags & 4 )
mpi_debug_free_limb_space(a->d, info); m_free( a->d );
#else else {
mpi_free_limb_space(a->d); #ifdef M_DEBUG
#endif mpi_debug_free_limb_space(a->d, info);
if( a->flags & ~3 ) #else
mpi_free_limb_space(a->d);
#endif
}
if( a->flags & ~7 )
log_bug("invalid flag value in mpi\n"); log_bug("invalid flag value in mpi\n");
m_free(a); 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 * Note: This copy function should not interpret the MPI
* but copy it transparently. * but copy it transparently.
@ -246,7 +291,13 @@ mpi_copy( MPI a )
int i; int i;
MPI b; 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 #ifdef M_DEBUG
b = mpi_is_secure(a)? mpi_debug_alloc_secure( a->nlimbs, info ) b = mpi_is_secure(a)? mpi_debug_alloc_secure( a->nlimbs, info )
: mpi_debug_alloc( a->nlimbs, info ); : mpi_debug_alloc( a->nlimbs, info );

View File

@ -103,15 +103,6 @@ main(int argc, char **argv)
if( argc < 1 ) if( argc < 1 )
my_usage(); 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++ ) for(n=0,i=1; i < argc; i++ )
n += strlen(argv[i]) + 1; n += strlen(argv[i]) + 1;
p = m_alloc( 100 + n ); p = m_alloc( 100 + n );

View File

@ -1,3 +1,7 @@
Mon Aug 3 17:06:00 1998 Werner Koch (wk@(none))
* secmem.c (MAP_ANON): Add a macro test
Wed Jul 29 14:53:34 1998 Werner Koch (wk@(none)) Wed Jul 29 14:53:34 1998 Werner Koch (wk@(none))
* ttyio.c (tty_get_answer_is_yes): New. * ttyio.c (tty_get_answer_is_yes): New.

View File

@ -706,6 +706,8 @@ iobuf_pop_filter( IOBUF a, int (*f)(void *opaque, int control,
m_free(a->d.buf); m_free(a->d.buf);
memcpy(a,b, sizeof *a); memcpy(a,b, sizeof *a);
m_free(b); 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 */ else if( !b->chain ) { /* remove the last iobuf from the chain */
log_bug("Ohh jeee, trying to remove a head filter\n"); log_bug("Ohh jeee, trying to remove a head filter\n");

View File

@ -35,6 +35,9 @@
#include "util.h" #include "util.h"
#include "i18n.h" #include "i18n.h"
#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
#define MAP_ANONYMOUS MAP_ANON
#endif
#define DEFAULT_POOLSIZE 8196 #define DEFAULT_POOLSIZE 8196
@ -105,10 +108,10 @@ init_pool( size_t n)
if( disable_secmem ) if( disable_secmem )
log_bug("secure memory is disabled"); log_bug("secure memory is disabled");
#if HAVE_MMAP && defined(MAP_ANONYMOUS) #if HAVE_MMAP && defined(MAP_ANON)
poolsize = (poolsize + 4095) & ~4095; poolsize = (poolsize + 4095) & ~4095;
pool = mmap( 0, poolsize, PROT_READ|PROT_WRITE, pool = mmap( 0, poolsize, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); MAP_PRIVATE|MAP_ANON, -1, 0);
if( pool == (void*)-1 ) if( pool == (void*)-1 )
log_error("can't mmap pool of %u bytes: %s - using malloc\n", log_error("can't mmap pool of %u bytes: %s - using malloc\n",
(unsigned)poolsize, strerror(errno)); (unsigned)poolsize, strerror(errno));