1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

added option export

This commit is contained in:
Werner Koch 1998-02-13 20:58:50 +00:00
parent b9fccd69e4
commit f477447d9a
43 changed files with 734 additions and 284 deletions

27
g10/ChangeLog Normal file
View file

@ -0,0 +1,27 @@
Fri Feb 13 20:18:14 1998 Werner Koch (wk@isil.d.shuttle.de)
* ringedit.c (enum_keyblocks, keyring_enum): New.
Fri Feb 13 19:33:40 1998 Werner Koch (wk@isil.d.shuttle.de)
* export.c: Add functionality.
* keygen.c (generate_keypair): Moved the leading comment behind the
key packet.
* kbnode.c (walk_kbnode): Fixed.
* g10.c (main): listing armored keys now work.
Fri Feb 13 16:17:43 1998 Werner Koch (wk@isil.d.shuttle.de)
* parse-packet.c (parse_publickey, parse_signature): Fixed calls
to mpi_read used for ELG b.
Fri Feb 13 15:13:23 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (main): changed formatting of help output.
Thu Feb 12 22:24:42 1998 Werner Koch (wk@frodo)
* pubkey-enc.c (get_session_key): rewritten

View file

@ -85,7 +85,6 @@ POSUB = @POSUB@
RANLIB = @RANLIB@
VERSION = @VERSION@
ZLIBS = @ZLIBS@
ZLIB_SUBDIR = @ZLIB_SUBDIR@
INCLUDES = -I$(top_srcdir)/include
EXTRA_DIST = OPTIONS pubring.g10

View file

@ -182,7 +182,7 @@ encode_crypt( const char *filename, STRLIST remusr )
goto leave;
}
else if( opt.verbose )
log_error("reading from '%s'\n", filename? filename: "[stdin]");
log_info("reading from '%s'\n", filename? filename: "[stdin]");
if( !(out = open_outfile( filename, opt.armor? 1:0 )) ) {
rc = G10ERR_CREATE_FILE; /* or user said: do not overwrite */

View file

@ -31,17 +31,109 @@
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "main.h"
/****************
* Make a new keyring from all internal keyrings (if no user is given)
* or for all selected users.
* Export the public keys (to standard out or --outout).
* Depending on opt.armor the output is armored.
* If USERS is NULL, the complete ring wil. be exported.
*/
int
export_pubkeys( STRLIST users )
{
log_fatal("Not yet implemented");
return 0;
int rc = 0;
armor_filter_context_t afx;
compress_filter_context_t zfx;
IOBUF out = NULL;
PACKET pkt;
KBNODE keyblock = NULL;
KBNODE kbctx, node;
KBPOS kbpos;
STRLIST sl;
int all = !users;
int any=0;
memset( &afx, 0, sizeof afx);
memset( &zfx, 0, sizeof zfx);
init_packet( &pkt );
if( !(out = open_outfile( NULL, 0 )) ) {
rc = G10ERR_CREATE_FILE;
goto leave;
}
if( opt.armor ) {
afx.what = 1;
iobuf_push_filter( out, armor_filter, &afx );
}
if( opt.compress )
iobuf_push_filter( out, compress_filter, &zfx );
if( all ) {
rc = enum_keyblocks( 0, &kbpos, &keyblock );
if( rc ) {
if( rc != -1 )
log_error("enum_keyblocks(open) failed: %s\n", g10_errstr(rc) );
goto leave;
}
all = 2;
}
/* use the correct sequence. strlist_last,prev do work correct with
* NULL pointers :-) */
for( sl=strlist_last(users); sl || all ; sl=strlist_prev( users, sl )) {
if( all ) { /* get the next user */
rc = enum_keyblocks( 1, &kbpos, &keyblock );
if( rc == -1 ) /* EOF */
break;
if( rc ) {
log_error("enum_keyblocks(read) failed: %s\n", g10_errstr(rc));
break;
}
}
else {
/* search the userid */
rc = find_keyblock_byname( &kbpos, sl->d );
if( rc ) {
log_error("%s: user not found: %s\n", sl->d, g10_errstr(rc) );
rc = 0;
continue;
}
/* read the keyblock */
rc = read_keyblock( &kbpos, &keyblock );
}
if( rc ) {
log_error("certificate read problem: %s\n", g10_errstr(rc));
goto leave;
}
/* and write it */
for( kbctx=NULL; (node = walk_kbnode( keyblock, &kbctx, 0 )); ) {
if( (rc = build_packet( out, node->pkt )) ) {
log_error("build_packet(%d) failed: %s\n",
node->pkt->pkttype, g10_errstr(rc) );
rc = G10ERR_WRITE_FILE;
goto leave;
}
}
any++;
}
if( rc == -1 )
rc = 0;
leave:
if( all == 2 )
enum_keyblocks( 2, &kbpos, &keyblock ); /* close */
release_kbnode( keyblock );
if( rc || !any )
iobuf_cancel(out);
else
iobuf_close(out);
if( !any )
log_info("warning: nothing exported\n");
return rc;
}

232
g10/g10.c
View file

@ -41,11 +41,85 @@
#include "status.h"
static ARGPARSE_OPTS opts[] = {
{ 300, NULL, 0, N_("\vCommands:\n ") },
{ 's', "sign", 0, N_("make a signature")},
{ 539, "clearsign", 0, N_("make a clear text signature") },
{ 'b', "detach-sign", 0, N_("make a detached signature")},
{ 'e', "encrypt", 0, N_("encrypt data")},
{ 'c', "symmetric", 0, N_("encryption only with symmetric cipher")},
{ 507, "store", 0, N_("store only")},
{ 'd', "decrypt", 0, N_("decrypt data (default)")},
{ 'k', "list-keys", 0, N_("list keys")},
{ 508, "check-keys",0, N_("check signatures on a key in the keyring")},
{ 515, "fingerprint", 0, N_("show the fingerprints")},
{ 521, "list-packets",0,N_("list only the sequence of packets")},
{ 503, "gen-key", 0, N_("generate a new key pair")},
{ 506, "sign-key" ,0, N_("make a signature on a key in the keyring")},
{ 505, "delete-key",0, N_("remove key from the public keyring")},
{ 524, "edit-sig" ,0, N_("edit a key signature")},
{ 525, "change-passphrase", 0, N_("change the passphrase of your secret keyring")},
{ 537, "export" , 0, N_("export keys") },
{ 530, "import", 0 , N_("import/merge keys")},
{ 301, NULL, 0, N_("\v\nOptions:\n ") },
{ 'a', "armor", 0, N_("create ascii armored output")},
{ 'o', "output", 2, N_("use as output file")},
{ 'u', "local-user",2, N_("use this user-id to sign or decrypt")},
{ 'r', "remote-user", 2, N_("use this user-id for encryption")},
{ 'v', "verbose", 0, N_("verbose") },
{ 'z', NULL, 1, N_("set compress level (0 disables)") },
{ 't', "textmode", 0, N_("use canonical text mode")},
{ 'n', "dry-run", 0, N_("don't make any changes") },
{ 500, "batch", 0, N_("batch mode: never ask")},
{ 501, "yes", 0, N_("assume yes on most questions")},
{ 502, "no", 0, N_("assume no on most questions")},
{ 509, "keyring" ,2, N_("add this keyring to the list of keyrings")},
{ 517, "secret-keyring" ,2, N_("add this secret keyring to the list")},
{ 518, "options" , 2, N_("read options from file")},
{ 510, "debug" ,4|16, N_("set debugging flags")},
{ 511, "debug-all" ,0, N_("enable full debugging")},
{ 512, "status-fd" ,1, N_("write status info to this fd") },
{ 534, "no-comment", 0, N_("do not write comment packets")},
{ 535, "completes-needed", 1, N_("(default is 1)")},
{ 536, "marginals-needed", 1, N_("(default is 3)")},
{ 527, "cipher-algo", 2 , N_("select default cipher algorithm")},
{ 528, "pubkey-algo", 2 , N_("select default puplic key algorithm")},
{ 529, "digest-algo", 2 , N_("select default message digest algorithm")},
{ 302, NULL, 0, N_("\v\nExamples:\n\n"
" -se -r Bob [file] sign and encrypt for user Bob\n"
" -sat [file] make a clear text signature\n"
" -sb [file] make a detached signature\n"
" -k [userid] show keys\n"
" -kc [userid] show fingerprint\n" ) },
/* hidden options */
{ 532, "quick-random", 0, "\r"},
{ 526, "no-verbose", 0, "\r"},
{ 538, "trustdb-name", 2, "\r" },
{ 540, "no-secmem-warning", 0, "\r" }, /* used only by regression tests */
{ 519, "no-armor", 0, "\r"},
{ 520, "no-default-keyring", 0, "\r" },
{ 522, "no-greeting", 0, "\r" },
{ 523, "passphrase-fd",1, "\r" },
{ 541, "no-operation", 0, "\r" }, /* used by regression tests */
{0} };
enum cmd_values { aNull = 0,
aSym, aStore, aEncr, aKeygen, aSign, aSignEncr,
aSignKey, aClearsign, aListPackets, aEditSig,
aKMode, aKModeC, aChangePass, aImport,
aExport,
aExport, aCheckKeys,
aNOP };
@ -59,7 +133,7 @@ strusage( int level )
switch( level ) {
case 10:
case 0: p = "g10 - v" VERSION "; "
"Copyright 1997 Werner Koch (dd9jn)\n" ; break;
"Copyright 1998 Werner Koch (dd9jn)\n" ; break;
case 13: p = "g10"; break;
case 14: p = VERSION; break;
case 1:
@ -105,7 +179,7 @@ i18n_init(void)
static void
wrong_args( const char *text)
{
fputs(_("Usage: g10 [options] "),stderr);
fputs(_("usage: g10 [options] "),stderr);
fputs(text,stderr);
putc('\n',stderr);
g10_exit(2);
@ -152,63 +226,28 @@ 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_pubkey_algo || check_pubkey_algo(opt.def_pubkey_algo) )
log_error(_("selected pubkey 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.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"));
}
void
main( int argc, char **argv )
{
static ARGPARSE_OPTS opts[] = {
{ 'a', "armor", 0, N_("create ascii armored output")},
{ 'v', "verbose", 0, N_("verbose") },
{ 'z', NULL, 1, N_("set compress level (0 disables)") },
{ 'n', "dry-run", 0, N_("don't make any changes") },
{ 'c', "symmetric", 0, N_("do only a symmetric encryption")},
{ 'o', "output", 2, N_("use as output file")},
{ 500, "batch", 0, N_("batch mode: never ask")},
{ 501, "yes", 0, N_("assume yes on most questions")},
{ 502, "no", 0, N_("assume no on most questions")},
{ 503, "gen-key", 0, N_("generate a new key pair")},
{ 504, "add-key", 0, N_("add key to the public keyring")},
{ 505, "delete-key",0, N_("remove key from public keyring")},
{ 506, "sign-key" ,0, N_("make a signature on a key in the keyring")},
{ 507, "store", 0, N_("store only")},
{ 508, "check-key" ,0, N_("check signatures on a key in the keyring")},
{ 509, "keyring" ,2, N_("add this keyring to the list of keyrings")},
{ 's', "sign", 0, N_("make a signature")},
{ 't', "textmode", 0, N_("use canonical text mode")},
{ 'b', "detach-sign", 0, N_("make a detached signature")},
{ 'e', "encrypt", 0, N_("encrypt data")},
{ 'd', "decrypt", 0, N_("decrypt data (default)")},
{ 'u', "local-user",2, N_("use this user-id to sign or decrypt")},
{ 'r', "remote-user", 2, N_("use this user-id for encryption")},
{ 'k', NULL , 0, N_("list keys")},
{ 510, "debug" ,4|16, N_("set debugging flags")},
{ 511, "debug-all" ,0, N_("enable full debugging")},
{ 512, "status-fd" ,1, N_("write status info to this fd") },
{ 515, "fingerprint", 0, N_("show the fingerprints")},
{ 517, "secret-keyring" ,2, N_("add this secret keyring to the list")},
{ 518, "options" , 2, N_("read options from file")},
{ 519, "no-armor", 0, "\r"},
{ 520, "no-default-keyring", 0, "\r" },
{ 521, "list-packets",0,N_("list only the sequence of packets")},
{ 522, "no-greeting", 0, "\r" },
{ 523, "passphrase-fd",1, "\r" },
{ 524, "edit-sig" ,0, N_("edit a key signature")},
{ 525, "change-passphrase", 0, N_("change the passphrase of your secret keyring")},
{ 526, "no-verbose", 0, "\r"},
{ 527, "cipher-algo", 2 , N_("select default cipher algorithm")},
{ 528, "pubkey-algo", 2 , N_("select default puplic key algorithm")},
{ 529, "digest-algo", 2 , N_("select default message digest algorithm")},
{ 530, "import", 0 , N_("put public keys into the trustdb")},
{ 532, "quick-random", 0, "\r"},
{ 534, "no-comment", 0, N_("do not write comment packets")},
{ 535, "completes-needed", 1, N_("(default is 1)")},
{ 536, "marginals-needed", 1, N_("(default is 3)")},
{ 537, "export", 0, N_("export all or the given keys") },
{ 538, "trustdb-name", 2, "\r" },
{ 539, "clearsign", 0, N_("make a clear text signature") },
{ 540, "no-secmem-warning", 0, "\r" }, /* used only by regression tests */
{ 541, "no-operation", 0, "\r" }, /* used by regression tests */
{0} };
ARGPARSE_ARGS pargs;
IOBUF a;
int rc=0;
@ -236,6 +275,7 @@ main( int argc, char **argv )
* secmem_init() somewhere after the option parsing
*/
log_set_name("g10");
i18n_init();
opt.compress = -1; /* defaults to standard compress level */
opt.def_cipher_algo = CIPHER_ALGO_BLOWFISH;
@ -278,9 +318,11 @@ main( int argc, char **argv )
if( parse_debug )
log_info(_("note: no default option file '%s'\n"), configname );
}
else
log_fatal(_("option file '%s': %s\n"),
else {
log_error(_("option file '%s': %s\n"),
configname, strerror(errno) );
g10_exit(1);
}
m_free(configname); configname = NULL;
}
if( parse_debug && configname )
@ -291,9 +333,7 @@ main( int argc, char **argv )
while( optfile_parse( configfp, configname, &configlineno,
&pargs, opts) ) {
switch( pargs.r_opt ) {
case 'v': opt.verbose++;
opt.list_sigs=1;
break;
case 'v': opt.verbose++; opt.list_sigs=1; break;
case 'z': opt.compress = pargs.r.ret_int; break;
case 'a': opt.armor = 1; opt.no_armor=0; break;
case 'd': break; /* it is default */
@ -322,7 +362,8 @@ main( int argc, char **argv )
case 503: set_cmd( &cmd, aKeygen); break;
case 506: set_cmd( &cmd, aSignKey); break;
case 507: set_cmd( &cmd, aStore); break;
case 508: opt.check_sigs = 1; opt.list_sigs = 1; break;
case 508: set_cmd( &cmd, aCheckKeys);
opt.check_sigs = 1; opt.list_sigs = 1; break;
case 509: add_keyring(pargs.r.ret_str); nrings++; break;
case 510: opt.debug |= pargs.r.ret_ulong; break;
case 511: opt.debug = ~0; break;
@ -374,27 +415,8 @@ main( int argc, char **argv )
goto next_pass;
}
m_free( configname ); configname = NULL;
if( !opt.def_cipher_algo || check_cipher_algo(opt.def_cipher_algo) ) {
log_error(_("selected cipher algorithm is invalid\n"));
errors++;
}
if( !opt.def_pubkey_algo || check_pubkey_algo(opt.def_pubkey_algo) ) {
log_error(_("selected pubkey algorithm is invalid\n"));
errors++;
}
if( !opt.def_digest_algo || check_digest_algo(opt.def_digest_algo) ) {
log_error(_("selected digest algorithm is invalid\n"));
errors++;
}
if( opt.completes_needed < 1 ) {
log_error(_("completes-needed must be greater than 0\n"));
errors++;
}
if( opt.marginals_needed < 2 ) {
log_error(_("marginals-needed must be greater than 1\n"));
errors++;
}
if( errors )
check_opts();
if( log_get_errorcount(0) )
g10_exit(2);
if( greeting ) {
@ -541,6 +563,7 @@ main( int argc, char **argv )
g10_errstr(rc) );
break;
case aCheckKeys:
case aKMode: /* list keyring */
if( !argc ) { /* list the default public keyrings */
int i, seq=0;
@ -563,14 +586,23 @@ main( int argc, char **argv )
}
}
else if( cmd == aCheckKeys ) {
log_error("will be soon: --check-keys user-ids\n");
}
else if( argc == 1) { /* list the given keyring */
if( !(a = iobuf_open(fname)) )
log_fatal(_("can't open '%s'\n"), fname_print);
proc_packets( a );
iobuf_close(a);
log_error(_("can't open '%s'\n"), fname_print);
else {
if( !opt.no_armor ) {
memset( &afx, 0, sizeof afx);
iobuf_push_filter( a, armor_filter, &afx );
}
proc_packets( a );
iobuf_close(a);
}
}
else
wrong_args(_("-k[v][v][v][c] [keyring]"));
wrong_args(_("-k[v][v][v][c] [keyring]") );
break;
case aKeygen: /* generate a key (interactive) */
@ -607,18 +639,20 @@ main( int argc, char **argv )
if( argc > 1 )
wrong_args(_("[filename]"));
if( !(a = iobuf_open(fname)) )
log_fatal(_("can't open '%s'\n"), fname_print);
if( !opt.no_armor ) {
/* push the armor filter, so it can peek at the input data */
memset( &afx, 0, sizeof afx);
iobuf_push_filter( a, armor_filter, &afx );
log_error(_("can't open '%s'\n"), fname_print);
else {
if( !opt.no_armor ) {
/* push the armor filter, so it can peek at the input data */
memset( &afx, 0, sizeof afx);
iobuf_push_filter( a, armor_filter, &afx );
}
if( cmd == aListPackets ) {
set_packet_list_mode(1);
opt.list_packets=1;
}
proc_packets( a );
iobuf_close(a);
}
if( cmd == aListPackets ) {
set_packet_list_mode(1);
opt.list_packets=1;
}
proc_packets( a );
iobuf_close(a);
break;
}

View file

@ -35,15 +35,34 @@
/****************
* Import the public keys from the given filename.
* Import is a somewhat misleading name, as we (only) add informations
* about the public keys into aout trustdb.
* Import the public keys from the given filename. Input may be armored.
* This function rejects alls keys which are not valid self signed on at
* least one userid. Only user ids which are self signed will be imported.
* Other signatures are not not checked.
*
* Actually this functtion does a merge, it works like this:
* FIXME: add handling for revocation certs
*
* - get the keyblock
* - check self-signatures and remove all userids and their isgnatures
* without/invalid self-signatures.
* - reject the keyblock, if we have no valid userid.
* - See wether we have this key already in one of our pubrings.
* If not, simply add it to the default keyring.
* - Compare the key and the self-signatures of the new and the one in
* our keyring. If they are differen something weird is going on;
* ask what to do.
* - See wether we have only non-self-signature on one user id; if not
* ask the user what to do.
* - compare the signatures: If we already have this signature, check
* that they compare okay, if not issue a warning and ask the user.
* (consider to look at the timestamp and use the newest?)
* - Simply add the signature. Can't verify here because we may not have
* the signatures public key yet; verification is done when putting it
* into the trustdb, which is done automagically as soon as this pubkey
* is used.
* - Proceed with next signature.
*
* NOTE: this function is not really needed and will be changed to
* a function which reads a plain textfile, describing a public
* key and its associated ownertrust. This can be used (together
* with the export function) to make a backup of the assigned
* ownertrusts.
*/
int
import_pubkeys( const char *filename )

View file

@ -177,11 +177,12 @@ walk_kbnode( KBNODE root, KBNODE *context, int all )
do {
if( !*context ) {
*context = root;
return root;
n = root;
}
else {
n = (*context)->next;
*context = n;
}
n = (*context)->next;
*context = n;
} while( !all && n && (n->private_flag & 1) );
return n;

View file

@ -51,6 +51,8 @@ struct keyblock_pos_struct {
int resno; /* resource number */
ulong offset; /* position information */
unsigned count; /* length of the keyblock in packets */
IOBUF fp; /* used by enum_keyblocks */
PACKET *pkt; /* ditto */
};
typedef struct keyblock_pos_struct KBPOS;
@ -144,6 +146,7 @@ int find_secret_keyblock_byname( KBPOS *kbpos, const char *username );
int lock_keyblock( KBPOS *kbpos );
void unlock_keyblock( KBPOS *kbpos );
int read_keyblock( KBPOS *kbpos, KBNODE *ret_root );
int enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root );
int insert_keyblock( KBPOS *kbpos, KBNODE root );
int delete_keyblock( KBPOS *kbpos );
int update_keyblock( KBPOS *kbpos, KBNODE root );

View file

@ -535,11 +535,11 @@ generate_keypair()
/* we create the packets as a tree of kbnodes. Because the structure
* we create is known in advance we simply generate a linked list
* The first packet is a comment packet, followed by the userid and
* the self signature.
* The first packet is a dummy comment packet which we flag
* as deleted. The very first packet must always be a CERT packet.
*/
pub_root = make_comment_node("#created by G10 pre-release " VERSION );
sec_root = make_comment_node("#created by G10 pre-release " VERSION );
pub_root = make_comment_node("#"); delete_kbnode(pub_root, pub_root);
sec_root = make_comment_node("#"); delete_kbnode(sec_root, sec_root);
tty_printf(_(
"We need to generate a lot of random bytes. It is a good idea to perform\n"
@ -557,6 +557,12 @@ generate_keypair()
rc = gen_dsa(nbits, pub_root, sec_root, dek, &skc );
else
BUG();
if( !rc ) {
add_kbnode( pub_root,
make_comment_node("#created by G10 release " VERSION ));
add_kbnode( sec_root,
make_comment_node("#created by G10 release " VERSION ));
}
if( !rc )
write_uid(pub_root, uid );
if( !rc )

View file

@ -437,6 +437,7 @@ parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
if( k->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
n = pktlen;
k->d.elg.a = mpi_read(inp, &n, 0); pktlen -=n;
n = pktlen;
k->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) {
printf("\telg a: ");
@ -502,6 +503,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
sig->d.elg.digest_start[1] = iobuf_get_noeof(inp); pktlen--;
n = pktlen;
sig->d.elg.a = mpi_read(inp, &n, 0 ); pktlen -=n;
n = pktlen;
sig->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) {
printf("\tdigest algo %d, begin of digest %02x %02x\n",

View file

@ -38,8 +38,10 @@
int
get_session_key( PKT_pubkey_enc *k, DEK *dek )
{
int i, j, c, rc = 0;
MPI dek_frame = mpi_alloc_secure(40);
int rc = 0;
MPI plain_dek = NULL;
byte *frame = NULL;
unsigned n, nframe;
u16 csum, csum2;
PKT_secret_cert *skc = m_alloc_clear( sizeof *skc );
@ -58,7 +60,8 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
skey.g = skc->d.elg.g;
skey.y = skc->d.elg.y;
skey.x = skc->d.elg.x;
elg_decrypt( dek_frame, k->d.elg.a, k->d.elg.b, &skey );
plain_dek = mpi_alloc_secure( mpi_get_nlimbs(skey.p) );
elg_decrypt( plain_dek, k->d.elg.a, k->d.elg.b, &skey );
memset( &skey, 0, sizeof skey );
}
#ifdef HAVE_RSA_CIPHER
@ -74,7 +77,8 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
skey.q = skc->d.rsa.rsa_q;
skey.d = skc->d.rsa.rsa_d;
skey.u = skc->d.rsa.rsa_u;
rsa_secret( dek_frame, k->d.rsa.rsa_integer, &skey );
plain_dek = mpi_alloc_secure( mpi_get_nlimbs(skey.n) );
rsa_secret( plain_dek, k->d.rsa.rsa_integer, &skey );
memset( &skey, 0, sizeof skey );
}
#endif/*HAVE_RSA_CIPHER*/
@ -83,9 +87,10 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
goto leave;
}
free_secret_cert( skc ); skc = NULL;
frame = mpi_get_buffer( plain_dek, &nframe, NULL );
mpi_free( plain_dek ); plain_dek = NULL;
/* Now get the DEK (data encryption key) from the dek_frame
/* Now get the DEK (data encryption key) from the frame
*
* Old versions encode the DEK in in this format (msb is left):
*
@ -101,51 +106,53 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
* CSUM
*/
if( DBG_CIPHER )
log_mpidump("DEK frame:", dek_frame );
for(i=0; mpi_getbyte(dek_frame, i) != -1; i++ )
log_hexdump("DEK frame:", frame, nframe );
for(n=0; n < nframe && !frame[n]; n++ ) /* skip leading zeroes */
;
for(i--; i >= 0 && !(c=mpi_getbyte(dek_frame, i)); i--)
; /* Skip leading zeroes */
if( i < 16 )
if( n + 7 > nframe )
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
if( c == 1 && mpi_getbyte(dek_frame,0) == 2 ) {
if( frame[n] == 1 && frame[nframe-1] == 2 ) {
log_error("old encoding of DEK is not supported\n");
rc = G10ERR_CIPHER_ALGO;
goto leave;
}
if( c != 2 ) /* somethink is wrong */
if( frame[n] != 2 ) /* somethink is wrong */
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
/* look for the zero byte */
for(i--; i > 4 ; i-- )
if( !mpi_getbyte(dek_frame,i) )
break;
if( i <= 4 ) /* zero byte not found */
for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */
;
n++; /* and the zero byte */
if( n + 4 > nframe )
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
/* next byte indicates the used cipher */
switch( mpi_getbyte(dek_frame, --i ) ) {
dek->keylen = nframe - (n+1) - 2;
dek->algo = frame[n++];
switch( dek->algo ) {
case CIPHER_ALGO_IDEA:
rc = G10ERR_NI_CIPHER;
goto leave;
case CIPHER_ALGO_BLOWFISH:
if( i != 22 ) /* length of blowfish is 20 (+2 bytes checksum) */
if( dek->keylen != 20 )
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
dek->algo = CIPHER_ALGO_BLOWFISH;
break;
case CIPHER_ALGO_BLOWFISH128:
if( i != 18 ) /* length of blowfish-128 is 16 (+2 bytes checksum) */
if( dek->keylen != 16 )
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
break;
case CIPHER_ALGO_CAST:
if( dek->keylen < 5 || dek->keylen > 16 )
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
dek->algo = CIPHER_ALGO_BLOWFISH128;
break;
default:
dek->algo = 0;
rc = G10ERR_CIPHER_ALGO;
goto leave;
}
/* copy the key to DEK and compare the checksum */
csum = mpi_getbyte(dek_frame, 1) << 8;
csum |= mpi_getbyte(dek_frame, 0);
dek->keylen = i - 2;
for( i--, csum2=0, j=0; i > 1; i-- )
csum2 += dek->key[j++] = mpi_getbyte(dek_frame, i);
csum = frame[nframe-2] << 8;
csum |= frame[nframe-1];
memcpy( dek->key, frame+n, dek->keylen );
for( csum2=0, n=0; n < dek->keylen; n++ )
csum2 += dek->key[n];
if( csum != csum2 ) {
rc = G10ERR_WRONG_SECKEY;
goto leave;
@ -154,7 +161,8 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
log_hexdump("DEK is:", dek->key, dek->keylen );
leave:
mpi_free(dek_frame);
mpi_free(plain_dek);
m_free(frame);
if( skc )
free_secret_cert( skc );
return rc;

View file

@ -77,6 +77,7 @@ static int keyring_search( PACKET *pkt, KBPOS *kbpos, IOBUF iobuf );
static int keyring_search2( PUBKEY_FIND_INFO info, KBPOS *kbpos,
const char *fname);
static int keyring_read( KBPOS *kbpos, KBNODE *ret_root );
static int keyring_enum( KBPOS *kbpos, KBNODE *ret_root );
static int keyring_copy( KBPOS *kbpos, int mode, KBNODE root );
@ -297,6 +298,78 @@ read_keyblock( KBPOS *kbpos, KBNODE *ret_root )
return keyring_read( kbpos, ret_root );
}
/****************
* This functions can be used to read trough a complete keyring.
* Mode is: 0 = open
* 1 = read
* 2 = close
* all others are reserved!
* Note that you do not need a search prior to call this function,
* only handle is needed.
* NOTE: It is not alloed to do an insert/update/delte with this
* keyblock, if you want to do this, user search/read!
*/
int
enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
{
int rc = 0;
RESTBL *rentry;
if( !mode || mode == 100 ) {
int i;
kbpos->fp = NULL;
if( !mode )
i = 0;
else
i = kbpos->resno+1;
for(; i < MAX_RESOURCES; i++ )
if( resource_table[i].used && !resource_table[i].secret )
break;
if( i == MAX_RESOURCES )
return -1; /* no resources */
kbpos->resno = i;
rentry = check_pos( kbpos );
kbpos->fp = iobuf_open( rentry->fname );
if( !kbpos->fp ) {
log_error("can't open '%s'\n", rentry->fname );
return G10ERR_OPEN_FILE;
}
kbpos->pkt = NULL;
}
else if( mode == 1 ) {
int cont;
do {
cont = 0;
if( !kbpos->fp )
return G10ERR_GENERAL;
rc = keyring_enum( kbpos, ret_root );
if( rc == -1 ) {
assert( !kbpos->pkt );
rentry = check_pos( kbpos );
assert(rentry);
/* close */
enum_keyblocks(2, kbpos, ret_root );
/* and open the next one */
rc = enum_keyblocks(100, kbpos, ret_root );
if( !rc )
cont = 1;
}
} while(cont);
}
else if( kbpos->fp ) {
iobuf_close( kbpos->fp );
kbpos->fp = NULL;
/* release pending packet */
free_packet( kbpos->pkt );
m_free( kbpos->pkt );
}
return rc;
}
/****************
* Insert the keyblock described by ROOT into the keyring described
* by KBPOS. This actually appends the data to the keyfile.
@ -551,9 +624,8 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root )
if( rc )
release_kbnode( root );
else {
else
*ret_root = root;
}
free_packet( pkt );
m_free( pkt );
iobuf_close(a);
@ -561,6 +633,69 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root )
}
static int
keyring_enum( KBPOS *kbpos, KBNODE *ret_root )
{
PACKET *pkt;
int rc;
RESTBL *rentry;
KBNODE root = NULL;
int in_cert = 0;
if( !(rentry=check_pos(kbpos)) )
return G10ERR_GENERAL;
if( kbpos->pkt ) {
root = new_kbnode( kbpos->pkt );
kbpos->pkt = NULL;
}
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
while( (rc=parse_packet(kbpos->fp, pkt)) != -1 ) {
if( rc ) { /* ignore errors */
if( rc != G10ERR_UNKNOWN_PACKET ) {
log_error("read_keyblock: read error: %s\n", g10_errstr(rc) );
rc = G10ERR_INV_KEYRING;
goto ready;
}
free_packet( pkt );
continue;
}
/* make a linked list of all packets */
switch( pkt->pkttype ) {
case PKT_PUBLIC_CERT:
case PKT_SECRET_CERT:
if( in_cert ) { /* store this packet */
kbpos->pkt = pkt;
pkt = NULL;
goto ready;
}
in_cert = 1;
default:
if( !root )
root = new_kbnode( pkt );
else
add_kbnode( root, new_kbnode( pkt ) );
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
break;
}
}
ready:
if( rc == -1 && root )
rc = 0;
if( rc )
release_kbnode( root );
else
*ret_root = root;
free_packet( pkt );
m_free( pkt );
return rc;
}
/****************
* Peromf insert/delete/update operation.
@ -579,6 +714,8 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
if( !(rentry = check_pos( kbpos )) )
return G10ERR_GENERAL;
if( kbpos->fp )
BUG(); /* not allowed with such a handle */
/* open the source file */
fp = iobuf_open( rentry->fname );

View file

@ -796,14 +796,14 @@ edit_keysigs( const char *username )
/* search the userid */
rc = find_keyblock_byname( &kbpos, username );
if( rc ) {
log_error("user '%s' not found\n", username );
log_error("%s: user not found\n", username );
goto leave;
}
/* read the keyblock */
rc = read_keyblock( &kbpos, &keyblock );
if( rc ) {
log_error("error reading the certificate: %s\n", g10_errstr(rc) );
log_error("%s: certificate read problem: %s\n", username, g10_errstr(rc) );
goto leave;
}