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.
* compress and symmetric cipher preferences are now used.
Because there is no 3DES yet, this is replaced by Blowfish.
* We have added the Twofish as an experimental cipher algorithm.
Many thanks to Matthew Skala for doing this work.
Twofish is the AES submission from Schneier et al.; see
"www.counterpane.com/twofish.html" for more information.
* [talk about --emulate-encr-mpi-bug]
Noteworthy changes in version 0.3.2

5
README
View File

@ -22,7 +22,7 @@
"pub 1312G/FF3EAA0B 1998-02-09 Werner Koch <wk@isil.d.shuttle.de>"
"Key fingerprint = 8489 6CD0 1851 0E33 45DA CD67 036F 11B8 FF3E AA0B"
My standard key is now:
My usual key is now:
"pub 1024D/621CC013 1998-07-07 Werner Koch <werner.koch@guug.de>"
"Key fingerprint = ECAF 7590 EB34 43B5 C7CF 3ACB 6C7E E1B8 621C C013"
@ -42,7 +42,8 @@
IDEA (which is patented worldwide) and RSA (which is patented in
the United States until Sep 20, 2000).
GNUPG is in most aspects compatible with other OpenPGP implementations.
GNUPG is in almost all aspects compatible with other OpenPGP
implementations.
The default algorithms are now DSA and ELGamal. ELGamal for signing
is still available, but due to the larger size of such signatures it

1
THANKS
View File

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

17
TODO
View File

@ -1,5 +1,7 @@
* Fix Oscaris problems with the trustdb.
* Replace the SIGUSR1 stuff by semaphores to avoid loss of a signal.
* add test cases for invalid data (scrambled armor or other random data)
* fix the expire stuff for v4 packets.
@ -8,14 +10,16 @@
sig) into a compressed packet - or should we only compress the data?
what does pgp 5 do, what does OpenPGP say=
* invalid packets (Marco)
* invalid packets (Marco) und Markus Gruber
* add some sanity checks to read_keyblock, so that we are sure that
the minimal requirements are met (?)
the minimal requirements are met (?)
* what about the CR,LF in cleartext singatures?
* make preferences work
* decryption of message with multiple recipients does not work.
* preferences of hash algorithms are not yet used.
* rewrite --list-packets or put it into another tool.
@ -25,8 +29,6 @@
* Burn the buffers used by fopen(), or use read(2). Does this
really make sense?
* enable a SIGSEGV handler while using zlib functions
* Change the buffering to a mbuf like scheme? Need it for PSST anyway.
* add checking of armor trailers
* remove all "Fixmes"
@ -40,3 +42,8 @@
* replace getkey.c#enum_secret_keys
* OpenBSD has sometimes problems reading from /dev/random.
* change the fake_data stuff to mpi_set_opaque

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!).
(or 0 for standard preference record)
1 u32 next
30 byte preference data
Record type 6 (sigrec)
-------------

View File

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

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))
* 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.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 );

View File

@ -34,6 +34,7 @@
#include "util.h"
#include "main.h"
#include "filter.h"
#include "trustdb.h"
#include "i18n.h"
@ -93,7 +94,9 @@ encode_simple( const char *filename, int mode )
s2k->mode = opt.rfc1991? 0:1;
s2k->hash_algo = opt.def_digest_algo ? opt.def_digest_algo
: DEFAULT_DIGEST_ALGO;
cfx.dek = passphrase_to_dek( NULL, opt.def_cipher_algo, s2k, 2 );
cfx.dek = passphrase_to_dek( NULL,
opt.def_cipher_algo ? opt.def_cipher_algo
: DEFAULT_CIPHER_ALGO , s2k, 2 );
if( !cfx.dek || !cfx.dek->keylen ) {
rc = G10ERR_PASSPHRASE;
m_free(cfx.dek);
@ -218,7 +221,13 @@ encode_crypt( const char *filename, STRLIST remusr )
/* create a session key */
cfx.dek = m_alloc_secure( sizeof *cfx.dek );
cfx.dek->algo = opt.def_cipher_algo;
if( !opt.def_cipher_algo ) { /* try to get it from the prefs */
cfx.dek->algo = select_algo_from_prefs( pk_list, PREFTYPE_SYM );
if( cfx.dek->algo == -1 )
cfx.dek->algo = DEFAULT_CIPHER_ALGO;
}
else
cfx.dek->algo = opt.def_cipher_algo;
make_session_key( cfx.dek );
if( DBG_CIPHER )
log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen );
@ -253,8 +262,16 @@ encode_crypt( const char *filename, STRLIST remusr )
/* register the cipher filter */
iobuf_push_filter( out, cipher_filter, &cfx );
/* register the compress filter */
if( opt.compress )
iobuf_push_filter( out, compress_filter, &zfx );
if( opt.compress ) {
int compr_algo = select_algo_from_prefs( pk_list, PREFTYPE_COMPR );
if( !compr_algo )
; /* don't use compression */
else {
if( compr_algo == 1 )
zfx.algo = 1; /* default is 2 */
iobuf_push_filter( out, compress_filter, &zfx );
}
}
/* do the work */
if( (rc = build_packet( out, &pkt )) )
@ -293,7 +310,15 @@ encrypt_filter( void *opaque, int control,
else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
if( !efx->header_okay ) {
efx->cfx.dek = m_alloc_secure( sizeof *efx->cfx.dek );
efx->cfx.dek->algo = opt.def_cipher_algo;
if( !opt.def_cipher_algo ) { /* try to get it from the prefs */
efx->cfx.dek->algo =
select_algo_from_prefs( efx->pk_list, PREFTYPE_SYM );
if( efx->cfx.dek->algo == -1 )
efx->cfx.dek->algo = DEFAULT_CIPHER_ALGO;
}
else
efx->cfx.dek->algo = opt.def_cipher_algo;
make_session_key( efx->cfx.dek );
if( DBG_CIPHER )
log_hexdump("DEK is: ",

View File

@ -30,6 +30,7 @@
#include "util.h"
#include "cipher.h"
#include "memory.h"
#include "options.h"
void
free_symkey_enc( PKT_symkey_enc *enc )
@ -82,6 +83,10 @@ release_public_key_parts( PKT_public_key *pk )
mpi_free( pk->pkey[i] );
pk->pkey[i] = NULL;
}
if( pk->namehash ) {
m_free(pk->namehash);
pk->namehash = NULL;
}
}
@ -123,13 +128,22 @@ cp_data_block( byte *s )
PKT_public_key *
copy_public_key( PKT_public_key *d, PKT_public_key *s )
copy_public_key_new_namehash( PKT_public_key *d, PKT_public_key *s,
const byte *namehash )
{
int n, i;
if( !d )
d = m_alloc(sizeof *d);
memcpy( d, s, sizeof *d );
if( namehash ) {
d->namehash = m_alloc( 20 );
memcpy(d->namehash, namehash, 20 );
}
else if( s->namehash ) {
d->namehash = m_alloc( 20 );
memcpy(d->namehash, s->namehash, 20 );
}
n = pubkey_get_npkey( s->pubkey_algo );
if( !n )
d->pkey[0] = cp_fake_data(s->pkey[0]);
@ -140,6 +154,11 @@ copy_public_key( PKT_public_key *d, PKT_public_key *s )
return d;
}
PKT_public_key *
copy_public_key( PKT_public_key *d, PKT_public_key *s )
{
return copy_public_key_new_namehash( d, s, NULL );
}
PKT_signature *
copy_signature( PKT_signature *d, PKT_signature *s )

View File

@ -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);

View File

@ -685,6 +685,8 @@ lookup( PKT_public_key *pk, int mode, u32 *keyid,
KBNODE keyblock = NULL;
KBPOS kbpos;
int oldmode = set_packet_list_mode(0);
byte namehash[20];
int use_namehash=0;
rc = enum_keyblocks( 0, &kbpos, &keyblock );
if( rc ) {
@ -719,6 +721,10 @@ lookup( PKT_public_key *pk, int mode, u32 *keyid,
u32 aki[2];
keyid_from_pk( kk->pkt->pkt.public_key, aki );
cache_user_id( k->pkt->pkt.user_id, aki );
rmd160_hash_buffer( namehash,
k->pkt->pkt.user_id->name,
k->pkt->pkt.user_id->len );
use_namehash = 1;
k = kk;
break;
}
@ -799,7 +805,8 @@ lookup( PKT_public_key *pk, int mode, u32 *keyid,
if( k ) { /* found */
assert( k->pkt->pkttype == PKT_PUBLIC_KEY
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY );
copy_public_key( pk, k->pkt->pkt.public_key );
copy_public_key_new_namehash( pk, k->pkt->pkt.public_key,
use_namehash? namehash:NULL);
add_stuff_from_selfsig( keyblock, k );
if( ret_keyblock ) {
*ret_keyblock = keyblock;
@ -950,7 +957,7 @@ lookup_sk( PKT_secret_key *sk, int mode, u32 *keyid, const char *name )
/****************
* Enumerate all secret keys. Caller must use these procedure:
* Enumerate all primary secret keys. Caller must use these procedure:
* 1) create a void pointer and initialize it to NULL
* 2) pass this void pointer by reference to this function
* and provide space for the secret key (pass a buffer for sk)
@ -997,8 +1004,7 @@ enum_secret_keys( void **context, PKT_secret_key *sk )
while( (rc=parse_packet(c->iobuf, &pkt)) != -1 ) {
if( rc )
; /* e.g. unknown packet */
else if( pkt.pkttype == PKT_SECRET_KEY
|| pkt.pkttype == PKT_SECRET_SUBKEY ) {
else if( pkt.pkttype == PKT_SECRET_KEY ) {
copy_secret_key( sk, pkt.pkt.secret_key );
set_packet_list_mode(save_mode);
return 0; /* found */

View File

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

View File

@ -40,8 +40,9 @@
#include "status.h"
#include "i18n.h"
static void show_prefs( KBNODE keyblock, PKT_user_id *uid );
static void show_key_with_all_names( KBNODE keyblock,
int only_marked, int with_fpr, int with_subkeys );
int only_marked, int with_fpr, int with_subkeys, int with_prefs );
static void show_key_and_fingerprint( KBNODE keyblock );
static void show_fingerprint( PKT_public_key *pk );
static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock );
@ -256,7 +257,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified )
}
/* Ask whether we realy should sign these user id(s) */
tty_printf("\n");
show_key_with_all_names( keyblock, 1, 1, 0 );
show_key_with_all_names( keyblock, 1, 1, 0, 0 );
tty_printf("\n");
tty_printf(_(
"Are you really sure that you want to sign this key\n"
@ -544,7 +545,7 @@ keyedit_menu( const char *username, STRLIST locusr )
enum cmdids { cmdNONE = 0,
cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN,
cmdDEBUG, cmdSAVE, cmdADDUID, cmdDELUID, cmdADDKEY, cmdDELKEY,
cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST,
cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF,
cmdNOP };
static struct { const char *name;
enum cmdids id;
@ -573,6 +574,7 @@ keyedit_menu( const char *username, STRLIST locusr )
{ N_("toggle") , cmdTOGGLE , 1, N_("toggle between secret "
"and public key listing") },
{ N_("t" ) , cmdTOGGLE , 1, NULL },
{ N_("pref") , cmdPREF , 0, N_("list preferences") },
{ N_("passwd") , cmdPASSWD , 1, N_("change the passphrase") },
{ N_("trust") , cmdTRUST , 0, N_("change the ownertrust") },
@ -625,7 +627,7 @@ keyedit_menu( const char *username, STRLIST locusr )
tty_printf("\n");
if( redisplay ) {
show_key_with_all_names( cur_keyblock, 0, 0, 1 );
show_key_with_all_names( cur_keyblock, 0, 0, 1, 0 );
tty_printf("\n");
redisplay = 0;
}
@ -670,7 +672,7 @@ keyedit_menu( const char *username, STRLIST locusr )
break;
case cmdQUIT:
if( !modified )
if( !modified && !sec_modified )
goto leave;
if( !cpr_get_answer_is_yes("keyedit.save",_("Save changes? ")) ) {
if( cpr_enabled()
@ -680,11 +682,13 @@ keyedit_menu( const char *username, STRLIST locusr )
}
/* fall thru */
case cmdSAVE:
if( modified ) {
rc = update_keyblock( &keyblockpos, keyblock );
if( rc ) {
log_error(_("update failed: %s\n"), g10_errstr(rc) );
break;
if( modified || sec_modified ) {
if( modified ) {
rc = update_keyblock( &keyblockpos, keyblock );
if( rc ) {
log_error(_("update failed: %s\n"), g10_errstr(rc) );
break;
}
}
if( sec_modified ) {
rc = update_keyblock( &sec_keyblockpos, sec_keyblock );
@ -807,7 +811,7 @@ keyedit_menu( const char *username, STRLIST locusr )
break;
case cmdTRUST:
show_key_with_all_names( keyblock, 0, 0, 1 );
show_key_with_all_names( keyblock, 0, 0, 1, 0 );
tty_printf("\n");
if( edit_ownertrust( find_kbnode( keyblock,
PKT_PUBLIC_KEY )->pkt->pkt.public_key->local_id, 1 ) )
@ -816,6 +820,10 @@ keyedit_menu( const char *username, STRLIST locusr )
* are updated immediately */
break;
case cmdPREF:
show_key_with_all_names( keyblock, 0, 0, 0, 1 );
break;
case cmdNOP:
break;
@ -833,6 +841,45 @@ keyedit_menu( const char *username, STRLIST locusr )
}
/****************
* show preferences of a public keyblock.
*/
static void
show_prefs( KBNODE keyblock, PKT_user_id *uid )
{
KBNODE node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
PKT_public_key *pk;
byte *p;
int i;
size_t n;
byte namehash[20];
if( !node )
return; /* is a secret keyblock */
pk = node->pkt->pkt.public_key;
if( !pk->local_id ) {
log_error("oops: no LID\n");
return;
}
rmd160_hash_buffer( namehash, uid->name, uid->len );
p = get_pref_data( pk->local_id, namehash, &n );
if( !p )
return;
tty_printf(" ");
for(i=0; i < n; i+=2 ) {
if( p[i] )
tty_printf( " %c%d", p[i] == PREFTYPE_SYM ? 'S' :
p[i] == PREFTYPE_HASH ? 'H' :
p[i] == PREFTYPE_COMPR ? 'Z' : '?', p[i+1]);
}
tty_printf("\n");
m_free(p);
}
/****************
* Display the key a the user ids, if only_marked is true, do only
@ -840,7 +887,7 @@ keyedit_menu( const char *username, STRLIST locusr )
*/
static void
show_key_with_all_names( KBNODE keyblock, int only_marked,
int with_fpr, int with_subkeys )
int with_fpr, int with_subkeys, int with_prefs )
{
KBNODE node;
int i;
@ -850,6 +897,15 @@ show_key_with_all_names( KBNODE keyblock, int only_marked,
if( node->pkt->pkttype == PKT_PUBLIC_KEY
|| (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) {
PKT_public_key *pk = node->pkt->pkt.public_key;
int otrust=0, trust=0;
if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
/* do it here, so that debug messages don't clutter the
* output */
trust = query_trust_info(pk);
otrust = get_ownertrust_info( pk->local_id );
}
tty_printf("%s%c %4u%c/%08lX created: %s expires: %s",
node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
(node->flag & NODFLG_SELKEY)? '*':' ',
@ -859,9 +915,6 @@ show_key_with_all_names( KBNODE keyblock, int only_marked,
datestr_from_pk(pk),
expirestr_from_pk(pk) );
if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
int otrust, trust;
trust = query_trust_info(pk);
otrust = get_ownertrust_info( pk->local_id );
tty_printf(" trust: %c/%c", otrust, trust );
if( with_fpr )
show_fingerprint( pk );
@ -896,6 +949,8 @@ show_key_with_all_names( KBNODE keyblock, int only_marked,
tty_printf("(%d) ", i);
tty_print_string( uid->name, uid->len );
tty_printf("\n");
if( with_prefs )
show_prefs( keyblock, uid );
}
}
}

View File

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

View File

@ -171,6 +171,7 @@ proc_pubkey_enc( CTX c, PACKET *pkt )
PKT_pubkey_enc *enc;
int result = 0;
/* check whether the secret key is available and store in this case */
c->last_was_session_key = 1;
enc = pkt->pkt.pubkey_enc;
/*printf("enc: encrypted by a pubkey with keyid %08lX\n", enc->keyid[1] );*/
@ -208,7 +209,9 @@ proc_encrypted( CTX c, PACKET *pkt )
/*printf("dat: %sencrypted data\n", c->dek?"":"conventional ");*/
if( !c->dek && !c->last_was_session_key ) {
/* assume this is old conventional encrypted data */
c->dek = passphrase_to_dek( NULL, opt.def_cipher_algo, NULL, 0 );
c->dek = passphrase_to_dek( NULL,
opt.def_cipher_algo ? opt.def_cipher_algo
: DEFAULT_CIPHER_ALGO, NULL, 0 );
}
else if( !c->dek )
result = G10ERR_NO_SECKEY;
@ -223,6 +226,8 @@ proc_encrypted( CTX c, PACKET *pkt )
}
else {
log_error(_("decryption failed: %s\n"), g10_errstr(result));
/* FIXME: if this is secret key not available, try with
* other keys */
}
free_packet(pkt);
c->last_was_session_key = 0;
@ -707,7 +712,9 @@ do_proc_packets( CTX c, IOBUF a )
while( (rc=parse_packet(a, pkt)) != -1 ) {
/* cleanup if we have an illegal data structure */
if( c->dek && pkt->pkttype != PKT_ENCRYPTED ) {
log_error("oops: valid pubkey enc packet not followed by data\n");
/* FIXME: do we need to ave it in case we have no secret
* key for one of the next reciepents- we should check it
* here. */
m_free(c->dek); c->dek = NULL; /* burn it */
}
@ -889,7 +896,7 @@ proc_tree( CTX c, KBNODE node )
/* ask for file and hash it */
if( c->sigs_only )
rc = hash_datafiles( c->mfx.md, c->signed_data, c->sigfilename,
n1->pkt->pkt.onepass_sig->sig_class == 0x01 );
n1? (n1->pkt->pkt.onepass_sig->sig_class == 0x01):0 );
else
rc = ask_for_detached_datafile( &c->mfx,
iobuf_get_fname(c->iobuf));

View File

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

View File

@ -112,6 +112,7 @@ typedef struct {
byte pubkey_usage; /* for now only used to pass it to getkey() */
ulong local_id; /* internal use, valid if > 0 */
u32 keyid[2]; /* calculated by keyid_from_pk() */
byte *namehash; /* if != NULL: found by this name */
MPI pkey[PUBKEY_MAX_NPKEY];
} PKT_public_key;
@ -235,6 +236,8 @@ int copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff );
int skip_some_packets( IOBUF inp, unsigned n );
const byte *parse_sig_subpkt( const byte *buffer,
sigsubpkttype_t reqtype, size_t *ret_n );
const byte *parse_sig_subpkt2( PKT_signature *sig,
sigsubpkttype_t reqtype, size_t *ret_n );
/*-- build-packet.c --*/
int build_packet( IOBUF inp, PACKET *pkt );
@ -257,6 +260,9 @@ void free_user_id( PKT_user_id *uid );
void free_comment( PKT_comment *rem );
void free_packet( PACKET *pkt );
PKT_public_key *copy_public_key( PKT_public_key *d, PKT_public_key *s );
PKT_public_key *copy_public_key_new_namehash( PKT_public_key *d,
PKT_public_key *s,
const byte *namehash );
PKT_secret_key *copy_secret_key( PKT_secret_key *d, PKT_secret_key *s );
PKT_signature *copy_signature( PKT_signature *d, PKT_signature *s );
PKT_user_id *copy_user_id( PKT_user_id *d, PKT_user_id *s );

View File

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

View File

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

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 "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);

View File

@ -67,19 +67,48 @@ do_check( PKT_secret_key *sk )
memcpy(save_iv, sk->protect.iv, 8 );
cipher_decrypt( cipher_hd, sk->protect.iv, sk->protect.iv, 8 );
csum = 0;
for(i=pubkey_get_npkey(sk->pubkey_algo);
i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
buffer = mpi_get_secure_buffer( sk->skey[i], &nbytes, NULL );
cipher_sync( cipher_hd );
assert( mpi_is_protected(sk->skey[i]) );
cipher_decrypt( cipher_hd, buffer, buffer, nbytes );
mpi_set_buffer( sk->skey[i], buffer, nbytes, 0 );
mpi_clear_protect_flag( sk->skey[i] );
csum += checksum_mpi( sk->skey[i] );
m_free( buffer );
if( sk->version >= 4 && !(opt.emulate_bugs & EMUBUG_ENCR_MPI) ) {
int ndata;
byte *p, *data;
i = pubkey_get_npkey(sk->pubkey_algo);
assert( mpi_is_opaque( sk->skey[i] ) );
p = mpi_get_opaque( sk->skey[i], &ndata );
data = m_alloc_secure( ndata );
cipher_decrypt( cipher_hd, data, p, ndata );
mpi_free( sk->skey[i] ); sk->skey[i] = NULL ;
p = data;
csum = checksum( data, ndata);
if( ndata < 2 )
log_bug("not enough bytes for checksum\n");
sk->csum = data[ndata-2] << 8 | data[ndata-1];
/* must check it here otherwise the mpi_read_xx would fail
* because the length das an abritary value */
if( sk->csum == csum ) {
for( ; i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
nbytes = ndata;
sk->skey[i] = mpi_read_from_buffer(p, &nbytes, 1 );
ndata -= nbytes;
p += nbytes;
}
}
m_free(data);
}
if( opt.emulate_bugs & EMUBUG_GPGCHKSUM ) {
csum = sk->csum;
else {
for(i=pubkey_get_npkey(sk->pubkey_algo);
i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
buffer = mpi_get_secure_buffer( sk->skey[i], &nbytes, NULL );
cipher_sync( cipher_hd );
assert( mpi_is_protected(sk->skey[i]) );
cipher_decrypt( cipher_hd, buffer, buffer, nbytes );
mpi_set_buffer( sk->skey[i], buffer, nbytes, 0 );
mpi_clear_protect_flag( sk->skey[i] );
csum += checksum_mpi( sk->skey[i] );
m_free( buffer );
}
if( opt.emulate_bugs & EMUBUG_GPGCHKSUM ) {
csum = sk->csum;
}
}
cipher_close( cipher_hd );
/* now let's see whether we have used the right passphrase */
@ -190,21 +219,26 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek )
cipher_setkey( cipher_hd, dek->key, dek->keylen );
cipher_setiv( cipher_hd, NULL );
cipher_encrypt( cipher_hd, sk->protect.iv, sk->protect.iv, 8 );
/* NOTE: we always recalculate the checksum because there are some
* test releases which calculated it wrong */
csum = 0;
for(i=pubkey_get_npkey(sk->pubkey_algo);
i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
csum += checksum_mpi_counted_nbits( sk->skey[i] );
buffer = mpi_get_buffer( sk->skey[i], &nbytes, NULL );
cipher_sync( cipher_hd );
assert( !mpi_is_protected(sk->skey[i]) );
cipher_encrypt( cipher_hd, buffer, buffer, nbytes );
mpi_set_buffer( sk->skey[i], buffer, nbytes, 0 );
mpi_set_protect_flag( sk->skey[i] );
m_free( buffer );
if( sk->version >= 4 && !(opt.emulate_bugs & EMUBUG_ENCR_MPI) ) {
BUG();
}
else {
/* NOTE: we always recalculate the checksum because there
* are some * test releases which calculated it wrong */
csum = 0;
for(i=pubkey_get_npkey(sk->pubkey_algo);
i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
csum += checksum_mpi_counted_nbits( sk->skey[i] );
buffer = mpi_get_buffer( sk->skey[i], &nbytes, NULL );
cipher_sync( cipher_hd );
assert( !mpi_is_protected(sk->skey[i]) );
cipher_encrypt( cipher_hd, buffer, buffer, nbytes );
mpi_set_buffer( sk->skey[i], buffer, nbytes, 0 );
mpi_set_protect_flag( sk->skey[i] );
m_free( buffer );
}
sk->csum = csum;
}
sk->csum = csum;
sk->is_protected = 1;
cipher_close( cipher_hd );
}

View File

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

View File

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

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");
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));

View File

@ -356,6 +356,7 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
{
int i;
ulong rnum = rec->recnum;
byte *p;
fprintf(fp, "rec %5lu, ", rnum );
@ -405,9 +406,15 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
putc('\n', fp);
break;
case RECTYPE_PREF:
fprintf(fp, "pref %lu, next=%lu\n",
rec->r.uid.lid,
rec->r.uid.next);
fprintf(fp, "pref %lu, next=%lu,",
rec->r.pref.lid, rec->r.pref.next);
for(i=0,p=rec->r.pref.data; i < ITEMS_PER_PREF_RECORD; i+=2,p+=2 ) {
if( *p )
fprintf(fp, " %c%d", *p == PREFTYPE_SYM ? 'S' :
*p == PREFTYPE_HASH ? 'H' :
*p == PREFTYPE_COMPR ? 'Z' : '?', p[1]);
}
putc('\n', fp);
break;
case RECTYPE_SIG:
fprintf(fp, "sig %lu, next=%lu,",
@ -537,6 +544,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
case RECTYPE_PREF: /* preference record */
rec->r.pref.lid = buftoulong(p); p += 4;
rec->r.pref.next = buftoulong(p); p += 4;
memcpy( rec->r.pref.data, p, 30 );
break;
case RECTYPE_SIG:
rec->r.sig.lid = buftoulong(p); p += 4;
@ -638,6 +646,7 @@ tdbio_write_record( TRUSTREC *rec )
case RECTYPE_PREF:
ulongtobuf(p, rec->r.pref.lid); p += 4;
ulongtobuf(p, rec->r.pref.next); p += 4;
memcpy( p, rec->r.pref.data, 30 );
break;
case RECTYPE_SIG:

View File

@ -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;

View File

@ -1593,8 +1593,6 @@ check_trust( PKT_public_key *pk, unsigned *r_trustlevel )
u32 keyid[2];
if( DBG_TRUST )
log_info("check_trust() called.\n");
keyid_from_pk( pk, keyid );
/* get the pubkey record */
@ -1762,6 +1760,90 @@ get_ownertrust_info( ulong lid )
}
byte *
get_pref_data( ulong lid, const byte *namehash, size_t *ret_n )
{
TRUSTREC rec;
ulong recno;
int rc;
if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) {
log_error("get_pref_data: read dir record failed\n");
return NULL;
}
for( recno=rec.r.dir.uidlist; recno; recno = rec.r.uid.next ) {
rc = tdbio_read_record( recno, &rec, RECTYPE_UID );
if( rc ) {
log_error("get_pref_data: read uid record failed: %s\n",
g10_errstr(rc));
return NULL;
}
if( rec.r.uid.prefrec
&& ( !namehash || !memcmp(namehash, rec.r.uid.namehash, 20) )) {
byte *buf;
/* found the correct one or the first one */
rc = tdbio_read_record( rec.r.uid.prefrec, &rec, RECTYPE_PREF );
if( rc ) {
log_error("get_pref_data: read pref record failed: %s\n",
g10_errstr(rc));
return NULL;
}
if( rec.r.pref.next )
log_info("warning: can't yet handle long pref records\n");
buf = m_alloc( ITEMS_PER_PREF_RECORD );
memcpy( buf, rec.r.pref.data, ITEMS_PER_PREF_RECORD );
*ret_n = ITEMS_PER_PREF_RECORD;
return buf;
}
}
return NULL;
}
/****************
* Check whether the algorithm is in one of the pref records
*/
int
is_algo_in_prefs( ulong lid, int preftype, int algo )
{
TRUSTREC rec;
ulong recno;
int i, rc;
byte *pref;
if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) {
log_error("is_algo_in_prefs: read dir record failed\n");
return 0;
}
for( recno=rec.r.dir.uidlist; recno; recno = rec.r.uid.next ) {
rc = tdbio_read_record( recno, &rec, RECTYPE_UID );
if( rc ) {
log_error("is_algo_in_prefs: read uid record failed: %s\n",
g10_errstr(rc));
return 0;
}
if( rec.r.uid.prefrec ) {
rc = tdbio_read_record( rec.r.uid.prefrec, &rec, RECTYPE_PREF );
if( rc ) {
log_error("is_algo_in_prefs: read pref record failed: %s\n",
g10_errstr(rc));
return 0;
}
if( rec.r.pref.next )
log_info("warning: can't yet handle long pref records\n");
pref = rec.r.pref.data;
for(i=0; i+1 < ITEMS_PER_PREF_RECORD; i+=2 ) {
if( pref[i] == preftype && pref[i+1] == algo )
return 1;
}
}
}
return 0;
}
/****************
* This function simply looks for the key in the trustdb
@ -1909,8 +1991,40 @@ insert_trust_record( PKT_public_key *orig_pk )
rc = 0;
}
else { /* build the prefrecord */
static struct {
sigsubpkttype_t subpkttype;
int preftype;
} prefs[] = {
{ SIGSUBPKT_PREF_SYM, PREFTYPE_SYM },
{ SIGSUBPKT_PREF_HASH, PREFTYPE_HASH },
{ SIGSUBPKT_PREF_COMPR, PREFTYPE_COMPR },
{ 0, 0 }
};
const byte *s;
size_t n;
int k, i;
assert(uidlist);
assert(!uidlist->help_pref);
uidlist->mark |= 1; /* mark valid */
i = 0;
for(k=0; prefs[k].subpkttype; k++ ) {
s = parse_sig_subpkt2( sig, prefs[k].subpkttype, &n );
if( s ) {
while( n ) {
if( !i || i >= ITEMS_PER_PREF_RECORD ) {
rec = m_alloc_clear( sizeof *rec );
rec->rectype = RECTYPE_PREF;
rec->next = uidlist->help_pref;
uidlist->help_pref = rec;
i = 0;
}
rec->r.pref.data[i++] = prefs[k].preftype;
rec->r.pref.data[i++] = *s++;
n--;
}
}
}
}
}
else if( 0 /* is revocation sig etc */ ) {
@ -1959,13 +2073,15 @@ insert_trust_record( PKT_public_key *orig_pk )
rec->r.uid.lid = dirrec.recnum;
rec->recnum = tdbio_new_recnum();
/* (preference records) */
for( rec2 = rec->help_pref; rec2; rec2 = rec2->next ) {
rec2->r.pref.lid = dirrec.recnum;
rec2->recnum = tdbio_new_recnum();
if( rec->help_pref ) {
for( rec2 = rec->help_pref; rec2; rec2 = rec2->next ) {
rec2->r.pref.lid = dirrec.recnum;
rec2->recnum = tdbio_new_recnum();
}
for( rec2 = rec->help_pref; rec2->next; rec2 = rec2->next )
rec2->next->r.pref.next = rec2->recnum;
rec->r.uid.prefrec = rec2->recnum;
}
for( rec2 = rec->help_pref; rec2; rec2 = rec2->next )
rec2->r.pref.next = rec2->next? rec2->next->recnum : 0;
rec->r.uid.prefrec = rec->help_pref? rec->help_pref->recnum : 0;
}
for(rec=uidlist_head; rec; rec = rec->next )
rec->r.uid.next = rec->next? rec->next->recnum : 0;

View File

@ -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 );

View File

@ -50,6 +50,7 @@ typedef struct mpi_struct {
int sign; /* indicates a negative number */
unsigned flags; /* bit 0: array must be allocated in secure memory space */
/* bit 1: the mpi is encrypted */
/* bit 2: the limb is a pointer to some m_alloced data */
mpi_limb_t *d; /* array with the limbs */
} *MPI;
@ -80,6 +81,9 @@ typedef struct mpi_struct {
void mpi_resize( MPI a, unsigned nlimbs );
MPI mpi_copy( MPI a );
#endif
#define mpi_is_opaque(a) ((a) && ((a)->flags&4))
MPI mpi_set_opaque( MPI a, void *p, int len );
void *mpi_get_opaque( MPI a, int *len );
#define mpi_is_protected(a) ((a) && ((a)->flags&2))
#define mpi_set_protect_flag(a) ((a)->flags |= 2)
#define mpi_clear_protect_flag(a) ((a)->flags &= ~2)
@ -100,6 +104,7 @@ int mpi_write( IOBUF out, MPI a );
#else
MPI mpi_read(IOBUF inp, unsigned *nread, int secure);
#endif
MPI mpi_read_from_buffer(byte *buffer, unsigned *ret_nread, int secure);
int mpi_fromstr(MPI val, const char *str);
int mpi_print( FILE *fp, MPI a, int mode );
u32 mpi_get_keyid( MPI a, u32 *keyid );

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)
* 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.

View File

@ -193,12 +193,16 @@ mpi_free( MPI a )
return;
if( DBG_MEMORY )
log_debug("mpi_free\n" );
#ifdef M_DEBUG
mpi_debug_free_limb_space(a->d, info);
#else
mpi_free_limb_space(a->d);
#endif
if( a->flags & ~3 )
if( a->flags & 4 )
m_free( a->d );
else {
#ifdef M_DEBUG
mpi_debug_free_limb_space(a->d, info);
#else
mpi_free_limb_space(a->d);
#endif
}
if( a->flags & ~7 )
log_bug("invalid flag value in mpi\n");
m_free(a);
}
@ -232,6 +236,47 @@ mpi_set_secure( MPI a )
}
MPI
mpi_set_opaque( MPI a, void *p, int len )
{
if( !a ) {
#ifdef M_DEBUG
a = mpi_debug_alloc(0,"alloc_opaque");
#else
a = mpi_alloc(0);
#endif
}
if( a->flags & 4 )
m_free( a->d );
else {
#ifdef M_DEBUG
mpi_debug_free_limb_space(a->d, "alloc_opaque");
#else
mpi_free_limb_space(a->d);
#endif
}
a->d = p;
a->alloced = 0;
a->nlimbs = 0;
a->nbits = len;
a->flags = 4;
return a;
}
void *
mpi_get_opaque( MPI a, int *len )
{
if( !(a->flags & 4) )
log_bug("mpi_get_opaque on normal mpi\n");
if( len )
*len = a->nbits;
return a->d;
}
/****************
* Note: This copy function should not interpret the MPI
* but copy it transparently.
@ -246,7 +291,13 @@ mpi_copy( MPI a )
int i;
MPI b;
if( a ) {
if( a && (a->flags & 4) ) {
void *p = m_is_secure(a->d)? m_alloc_secure( a->nbits )
: m_alloc( a->nbits );
memcpy( p, a->d, a->nbits );
b = mpi_set_opaque( NULL, p, a->nbits );
}
else if( a ) {
#ifdef M_DEBUG
b = mpi_is_secure(a)? mpi_debug_alloc_secure( a->nlimbs, info )
: mpi_debug_alloc( a->nlimbs, info );

View File

@ -103,15 +103,6 @@ main(int argc, char **argv)
if( argc < 1 )
my_usage();
#if 0
shm_ID = atoi( argv[1] );
pool = shmat( shm_ID, 0, 0 );
if( pool == (void*)-1 )
log_fatal("shmat of %d failed: %s\n", shm_ID, strerror(errno));
log_info("attached to %p id=%d\n", pool, shm_ID );
getchar();
#endif
for(n=0,i=1; i < argc; i++ )
n += strlen(argv[i]) + 1;
p = m_alloc( 100 + n );

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))
* 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);
memcpy(a,b, sizeof *a);
m_free(b);
if( DBG_IOBUF )
log_debug("iobuf-%d.%d: popped filter\n", a->no, a->subno );
}
else if( !b->chain ) { /* remove the last iobuf from the chain */
log_bug("Ohh jeee, trying to remove a head filter\n");

View File

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