aboutsummaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
Diffstat (limited to 'g10')
-rw-r--r--g10/encode.c2
-rw-r--r--g10/g10.c47
-rw-r--r--g10/getkey.c13
-rw-r--r--g10/kbnode.c63
-rw-r--r--g10/keydb.h13
-rw-r--r--g10/keygen.c363
-rw-r--r--g10/keyid.c12
-rw-r--r--g10/main.h4
-rw-r--r--g10/mainproc.c14
-rw-r--r--g10/options.h2
-rw-r--r--g10/ringedit.c130
-rw-r--r--g10/seskey.c2
12 files changed, 439 insertions, 226 deletions
diff --git a/g10/encode.c b/g10/encode.c
index 3bcdbe909..53d03c038 100644
--- a/g10/encode.c
+++ b/g10/encode.c
@@ -218,7 +218,7 @@ encode_crypt( const char *filename, STRLIST remusr )
pkc = m_alloc_clear( sizeof *pkc );
pkc->pubkey_algo = DEFAULT_PUBKEY_ALGO;
- if( (rc = get_pubkey_by_name( pkc, remusr->d )) ) {
+ if( (rc = get_pubkey_byname( pkc, remusr->d )) ) {
last_rc = rc;
log_error("skipped '%s': %s\n", remusr->d, g10_errstr(rc) );
continue;
diff --git a/g10/g10.c b/g10/g10.c
index 495875ce2..777220aa1 100644
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -125,20 +125,21 @@ main( int argc, char **argv )
{ 510, "debug" ,4|16, "set debugging flags" },
{ 511, "debug-all" ,0, "enable full debugging"},
{ 512, "cache-all" ,0, "hold everything in memory"},
- { 513, "gen-prime" , 1, "\rgenerate a prime of length n" },
- { 514, "test" , 0, "\rdevelopment usage" },
+ { 513, "gen-prime" , 1, "\r" },
+ { 514, "test" , 0, "\r" },
{ 515, "change-passphrase", 0, "change the passphrase of your secret keyring"},
{ 515, "fingerprint", 0, "show the fingerprints"},
{ 516, "print-mds" , 0, "print all message digests"},
{ 517, "secret-keyring" ,2, "add this secret keyring to the list" },
{ 518, "config" , 2, "use this config file" },
+ { 519, "no-armor", 0, "\r"},
{0} };
ARGPARSE_ARGS pargs;
IOBUF a;
int rc;
enum { aNull, aSym, aStore, aEncr, aPrimegen, aKeygen, aSign, aSignEncr,
- aTest, aPrintMDs,
+ aTest, aPrintMDs, aSignKey,
} action = aNull;
int orig_argc;
char **orig_argv;
@@ -189,7 +190,7 @@ main( int argc, char **argv )
configfp = fopen( configname, "r" );
if( !configfp ) {
if( default_config ) {
- if( parse_verbose )
+ if( parse_verbose > 1 )
log_info("note: no default option file '%s'\n", configname );
}
else
@@ -197,7 +198,7 @@ main( int argc, char **argv )
configname, strerror(errno) );
m_free(configname); configname = NULL;
}
- if( parse_verbose )
+ if( parse_verbose > 1 )
log_info("reading options from '%s'\n", configname );
default_config = 0;
}
@@ -209,7 +210,7 @@ main( int argc, char **argv )
opt.list_sigs=1;
break;
case 'z': opt.compress = pargs.r.ret_int; break;
- case 'a': opt.armor = 1; break;
+ case 'a': opt.armor = 1; opt.no_armor=0; break;
case 'c': action = aSym; break;
case 'o': opt.outfile = pargs.r.ret_str;
if( opt.outfile[0] == '-' && !opt.outfile[1] )
@@ -235,6 +236,7 @@ main( int argc, char **argv )
case 501: opt.answer_yes = 1; break;
case 502: opt.answer_no = 1; break;
case 503: action = aKeygen; break;
+ case 506: action = aSignKey; break;
case 507: action = aStore; break;
case 508: opt.check_sigs = 1; opt.list_sigs = 1; break;
case 509: add_keyring(pargs.r.ret_str); nrings++; break;
@@ -254,6 +256,7 @@ main( int argc, char **argv )
goto next_pass;
}
break;
+ case 519: opt.no_armor=1; opt.armor=0; break;
default : errors++; pargs.err = configfp? 1:2; break;
}
}
@@ -270,7 +273,7 @@ main( int argc, char **argv )
set_debug();
if( opt.verbose > 1 )
set_packet_list_mode(1);
- if( !opt.batch && isatty(fileno(stdin)) ) {
+ if( opt.verbose && isatty(fileno(stdin)) ) {
if( *(s=strusage(10)) )
fputs(s, stderr);
if( *(s=strusage(30)) )
@@ -278,11 +281,14 @@ main( int argc, char **argv )
}
if( !sec_nrings ) { /* add default secret rings */
- add_keyring("../keys/secring.g10");
+ char *p = make_filename("~/.g10", "secring.g10", NULL );
+ add_secret_keyring(p);
+ m_free(p);
}
- if( !nrings ) { /* add default rings */
- add_keyring("../keys/ring.pgp");
- add_keyring("../keys/pubring.g10");
+ if( !nrings ) { /* add default ring */
+ char *p = make_filename("~/.g10", "pubring.g10", NULL );
+ add_keyring(p);
+ m_free(p);
}
if( argc ) {
@@ -323,10 +329,21 @@ main( int argc, char **argv )
log_error("sign_file('%s'): %s\n", fname_print, g10_errstr(rc) );
break;
+
case aSignEncr: /* sign and encrypt the given file */
usage(1); /* FIXME */
break;
+
+ case aSignKey: /* sign the key given as argument */
+ if( argc != 1 )
+ usage(1);
+ /* note: fname is the user id! */
+ if( (rc = sign_key(fname, locusr)) )
+ log_error("sign_key('%s'): %s\n", fname_print, g10_errstr(rc) );
+ break;
+
+
case aPrimegen:
if( argc )
usage(1);
@@ -356,9 +373,11 @@ main( int argc, char **argv )
usage(1);
if( !(a = iobuf_open(fname)) )
log_fatal("can't open '%s'\n", fname_print);
- /* 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( !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 );
+ }
proc_packets( a );
iobuf_close(a);
break;
diff --git a/g10/getkey.c b/g10/getkey.c
index b079cca19..67b86ccf3 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -83,9 +83,9 @@ add_keyring( const char *name )
* combine it with the keyblock stuff from ringedit.c
* For now we will simple add the filename as keyblock resource
*/
- rc = add_keyblock_resource( name );
+ rc = add_keyblock_resource( name, 0 );
if( rc )
- log_error("keyblock resource '%s': %s\n", name, rc );
+ log_error("keyblock resource '%s': %s\n", name, g10_errstr(rc) );
}
void
@@ -245,7 +245,7 @@ get_pubkey( PKT_public_cert *pkc, u32 *keyid )
* a pubkey with that algo.
*/
int
-get_pubkey_by_name( PKT_public_cert *pkc, const char *name )
+get_pubkey_byname( PKT_public_cert *pkc, const char *name )
{
int internal = 0;
int rc = 0;
@@ -304,7 +304,7 @@ get_seckey( PKT_secret_cert *skc, u32 *keyid )
* If NAME is NULL use the default certificate
*/
int
-get_seckey_by_name( PKT_secret_cert *skc, const char *name )
+get_seckey_byname( PKT_secret_cert *skc, const char *name, int unprotect )
{
STRLIST sl;
int rc=0;
@@ -319,8 +319,9 @@ get_seckey_by_name( PKT_secret_cert *skc, const char *name )
/* get the secret key (this may prompt for a passprase to
* unlock the secret key
*/
- if( (rc = check_secret_key( skc )) )
- goto leave;
+ if( unprotect )
+ if( (rc = check_secret_key( skc )) )
+ goto leave;
leave:
return rc;
diff --git a/g10/kbnode.c b/g10/kbnode.c
index d148cb450..a4ac40dc5 100644
--- a/g10/kbnode.c
+++ b/g10/kbnode.c
@@ -57,6 +57,36 @@ release_kbnode( KBNODE n )
/****************
+ * Append NODE to ROOT, ROOT must exist!
+ */
+void
+add_kbnode( KBNODE root, KBNODE node )
+{
+ KBNODE n1;
+
+ for(n1=root; n1->next; n1 = n1->next)
+ ;
+ n1->next = node;
+}
+
+/****************
+ * Append NODE to ROOT as child of ROOT
+ */
+void
+add_kbnode_as_child( KBNODE root, KBNODE node )
+{
+ KBNODE n1;
+
+ if( !(n1=root->child) )
+ root->child = node;
+ else {
+ for( ; n1->next; n1 = n1->next)
+ ;
+ n1->next = node;
+ }
+}
+
+/****************
* Return the parent node of KBNODE from the tree with ROOT
*/
KBNODE
@@ -72,8 +102,39 @@ find_kbparent( KBNODE root, KBNODE node )
}
}
}
- log_bug(NULL);
+ return NULL;
}
+/****************
+ * Walk through a tree of kbnodes. This functions returns
+ * the next kbnode for each call; before using the function the first
+ * time, the caller must set CONTEXT to NULL (This has simply the effect
+ * to start with ROOT).
+ */
+KBNODE
+walk_kbtree( KBNODE root, KBNODE *context )
+{
+ KBNODE n;
+
+ if( !*context ) {
+ *context = root;
+ return root;
+ }
+
+ n = *context;
+ if( n->child ) {
+ n = n->child;
+ *context = n;
+ }
+ else if( n->next ) {
+ n = n->next;
+ *context = n;
+ }
+ else if( (n = find_kbparent( root, n )) ) {
+ n = n->next;
+ *context = n;
+ }
+ return n;
+}
diff --git a/g10/keydb.h b/g10/keydb.h
index a81b258d7..58e62da48 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -66,13 +66,14 @@ void add_secret_keyring( const char *name );
void cache_public_cert( PKT_public_cert *pkc );
void cache_user_id( PKT_user_id *uid, u32 *keyid );
int get_pubkey( PKT_public_cert *pkc, u32 *keyid );
-int get_pubkey_by_name( PKT_public_cert *pkc, const char *name );
+int get_pubkey_byname( PKT_public_cert *pkc, const char *name );
int get_seckey( PKT_secret_cert *skc, u32 *keyid );
-int get_seckey_by_name( PKT_secret_cert *skc, const char *name );
+int get_seckey_byname( PKT_secret_cert *skc, const char *name, int unlock );
char*get_user_id_string( u32 *keyid );
char*get_user_id( u32 *keyid, size_t *rn );
/*-- keyid.c --*/
+int pubkey_letter( int algo );
u32 keyid_from_skc( PKT_secret_cert *skc, u32 *keyid );
u32 keyid_from_pkc( PKT_public_cert *pkc, u32 *keyid );
u32 keyid_from_sig( PKT_signature *sig, u32 *keyid );
@@ -87,14 +88,18 @@ byte *fingerprint_from_pkc( PKT_public_cert *pkc, size_t *ret_len );
/*-- kbnode.c --*/
KBNODE new_kbnode( PACKET *pkt );
void release_kbnode( KBNODE n );
+void add_kbnode( KBNODE root, KBNODE node );
+void add_kbnode_as_child( KBNODE root, KBNODE node );
KBNODE find_kbparent( KBNODE root, KBNODE node );
+KBNODE walk_kbtree( KBNODE root, KBNODE *context );
/*-- ringedit.c --*/
-int add_keyblock_resource( const char *filename );
+int add_keyblock_resource( const char *filename, int force );
int get_keyblock_handle( const char *filename, KBPOS *kbpos );
int search_keyblock( PACKET *pkt, KBPOS *kbpos );
+int search_keyblock_byname( KBPOS *kbpos, const char *username );
int lock_keyblock( KBPOS *kbpos );
-int unlock_keyblock( KBPOS *kbpos );
+void unlock_keyblock( KBPOS *kbpos );
int read_keyblock( KBPOS *kbpos, KBNODE *ret_root );
int insert_keyblock( KBPOS *kbpos, KBNODE root );
int delete_keyblock( KBPOS *kbpos );
diff --git a/g10/keygen.c b/g10/keygen.c
index a4ed697c4..47bc2b14f 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -30,6 +30,7 @@
#include "cipher.h"
#include "ttyio.h"
#include "options.h"
+#include "keydb.h"
#if 0
#define TEST_ALGO 1
@@ -88,52 +89,128 @@ checksum_mpi( MPI a )
static void
-write_uid( IOBUF out, const char *s, PKT_user_id **upkt )
+write_uid( KBNODE root, const char *s )
{
- PACKET pkt;
+ PACKET *pkt = m_alloc_clear(sizeof *pkt );
size_t n = strlen(s);
- int rc;
- pkt.pkttype = PKT_USER_ID;
- pkt.pkt.user_id = m_alloc( sizeof *pkt.pkt.user_id + n - 1 );
- pkt.pkt.user_id->len = n;
- strcpy(pkt.pkt.user_id->name, s);
- if( (rc = build_packet( out, &pkt )) )
- log_error("build_packet(user_id) failed: %s\n", g10_errstr(rc) );
- if( upkt ) {
- *upkt = pkt.pkt.user_id;
- pkt.pkt.user_id = NULL;
- }
- free_packet( &pkt );
+ pkt->pkttype = PKT_USER_ID;
+ pkt->pkt.user_id = m_alloc( sizeof *pkt->pkt.user_id + n - 1 );
+ pkt->pkt.user_id->len = n;
+ strcpy(pkt->pkt.user_id->name, s);
+ add_kbnode( root, new_kbnode( pkt ) );
}
static int
-write_selfsig( IOBUF out, PKT_public_cert *pkc, PKT_user_id *uid,
- PKT_secret_cert *skc )
+write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_cert *skc )
{
- PACKET pkt;
+ PACKET *pkt;
PKT_signature *sig;
+ PKT_user_id *uid;
int rc=0;
+ KBNODE kbctx, node;
+ PKT_public_cert *pkc;
if( opt.verbose )
log_info("writing self signature\n");
+ /* get the uid packet from the tree */
+ for( kbctx=NULL; (node=walk_kbtree( root, &kbctx)) ; ) {
+ if( node->pkt->pkttype == PKT_USER_ID )
+ break;
+ }
+ if( !node )
+ log_bug(NULL); /* no user id packet in tree */
+ uid = node->pkt->pkt.user_id;
+ /* get the pkc packet from the pub_tree */
+ for( kbctx=NULL; (node=walk_kbtree( pub_root, &kbctx)) ; ) {
+ if( node->pkt->pkttype == PKT_PUBLIC_CERT )
+ break;
+ }
+ if( !node )
+ log_bug(NULL);
+ pkc = node->pkt->pkt.public_cert;
+
+ /* and make the signature */
rc = make_keysig_packet( &sig, pkc, uid, skc, 0x13, DIGEST_ALGO_RMD160 );
if( rc ) {
log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) );
return rc;
}
- pkt.pkttype = PKT_SIGNATURE;
- pkt.pkt.signature = sig;
- if( (rc = build_packet( out, &pkt )) )
- log_error("build_packet(signature) failed: %s\n", g10_errstr(rc) );
- free_packet( &pkt );
+ pkt = m_alloc_clear( sizeof *pkt );
+ pkt->pkttype = PKT_SIGNATURE;
+ pkt->pkt.signature = sig;
+ add_kbnode( root, new_kbnode( pkt ) );
return rc;
}
+static int
+gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
+ PKT_secret_cert **ret_skc )
+{
+ int rc;
+ PACKET *pkt;
+ PKT_secret_cert *skc;
+ PKT_public_cert *pkc;
+ ELG_public_key pk;
+ ELG_secret_key sk;
+ unsigned nbytes;
+
+ elg_generate( &pk, &sk, nbits );
+
+ skc = m_alloc( sizeof *skc );
+ pkc = m_alloc( sizeof *pkc );
+ skc->timestamp = pkc->timestamp = make_timestamp();
+ skc->valid_days = pkc->valid_days = 0; /* fixme: make it configurable*/
+ skc->pubkey_algo = pkc->pubkey_algo = PUBKEY_ALGO_ELGAMAL;
+ memset(&pkc->mfx, 0, sizeof pkc->mfx);
+ pkc->d.elg.p = pk.p;
+ pkc->d.elg.g = pk.g;
+ pkc->d.elg.y = pk.y;
+ skc->d.elg.p = sk.p;
+ skc->d.elg.g = sk.g;
+ skc->d.elg.y = sk.y;
+ skc->d.elg.x = sk.x;
+
+ skc->d.elg.csum = checksum_mpi( skc->d.elg.x );
+ /* return an unprotected version of the skc */
+ *ret_skc = copy_secret_cert( NULL, skc );
+
+ if( !dek ) {
+ skc->d.elg.is_protected = 0;
+ skc->d.elg.protect_algo = 0;
+ }
+ else {
+ skc->d.elg.is_protected = 0;
+ skc->d.elg.protect_algo = CIPHER_ALGO_BLOWFISH;
+ randomize_buffer(skc->d.elg.protect.blowfish.iv, 8, 1);
+ rc = protect_secret_key( skc, dek );
+ if( rc ) {
+ log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
+ free_public_cert(pkc);
+ free_secret_cert(skc);
+ return rc;
+ }
+ }
+
+ pkt = m_alloc_clear(sizeof *pkt);
+ pkt->pkttype = PKT_PUBLIC_CERT;
+ pkt->pkt.public_cert = pkc;
+ add_kbnode(pub_root, new_kbnode( pkt ));
+
+ pkt = m_alloc_clear(sizeof *pkt);
+ pkt->pkttype = PKT_SECRET_CERT;
+ pkt->pkt.secret_cert = skc;
+ add_kbnode(sec_root, new_kbnode( pkt ));
+
+ return 0;
+}
+
+
+
#ifdef HAVE_RSA_CIPHER
static int
gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io, DEK *dek,
@@ -210,79 +287,12 @@ gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io, DEK *dek,
}
#endif /*HAVE_RSA_CIPHER*/
+
static int
-gen_elg(unsigned nbits, IOBUF pub_io, IOBUF sec_io, DEK *dek,
- PKT_public_cert **ret_pkc, PKT_secret_cert **ret_skc )
+gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
+ PKT_secret_cert **ret_skc )
{
- int rc;
- PACKET pkt1, pkt2;
- PKT_secret_cert *skc, *unprotected_skc;
- PKT_public_cert *pkc;
- ELG_public_key pk;
- ELG_secret_key sk;
- unsigned nbytes;
-
- init_packet(&pkt1);
- init_packet(&pkt2);
-
- elg_generate( &pk, &sk, nbits );
-
- skc = m_alloc( sizeof *skc );
- pkc = m_alloc( sizeof *pkc );
- skc->timestamp = pkc->timestamp = make_timestamp();
- skc->valid_days = pkc->valid_days = 0; /* fixme: make it configurable*/
- skc->pubkey_algo = pkc->pubkey_algo = PUBKEY_ALGO_ELGAMAL;
- memset(&pkc->mfx, 0, sizeof pkc->mfx);
- pkc->d.elg.p = pk.p;
- pkc->d.elg.g = pk.g;
- pkc->d.elg.y = pk.y;
- skc->d.elg.p = sk.p;
- skc->d.elg.g = sk.g;
- skc->d.elg.y = sk.y;
- skc->d.elg.x = sk.x;
-
- skc->d.elg.csum = checksum_mpi( skc->d.elg.x );
- unprotected_skc = copy_secret_cert( NULL, skc );
- if( !dek ) {
- skc->d.elg.is_protected = 0;
- skc->d.elg.protect_algo = 0;
- }
- else {
- skc->d.elg.is_protected = 0;
- skc->d.elg.protect_algo = CIPHER_ALGO_BLOWFISH;
- randomize_buffer(skc->d.elg.protect.blowfish.iv, 8, 1);
- rc = protect_secret_key( skc, dek );
- if( rc ) {
- log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
- goto leave;
- }
- }
-
- pkt1.pkttype = PKT_PUBLIC_CERT;
- pkt1.pkt.public_cert = pkc;
- pkt2.pkttype = PKT_SECRET_CERT;
- pkt2.pkt.secret_cert = skc;
-
- if( (rc = build_packet( pub_io, &pkt1 )) ) {
- log_error("build public_cert packet failed: %s\n", g10_errstr(rc) );
- goto leave;
- }
- if( (rc = build_packet( sec_io, &pkt2 )) ) {
- log_error("build secret_cert packet failed: %s\n", g10_errstr(rc) );
- goto leave;
- }
- *ret_pkc = pkt1.pkt.public_cert;
- pkt1.pkt.public_cert = NULL;
- *ret_skc = unprotected_skc;
- unprotected_skc = NULL;
-
-
- leave:
- free_packet(&pkt1);
- free_packet(&pkt2);
- if( unprotected_skc )
- free_secret_cert( unprotected_skc );
- return rc;
+ return G10ERR_GENERAL;
}
@@ -295,14 +305,14 @@ generate_keypair()
{
char *answer;
unsigned nbits;
- char *pub_fname = "./pubring.g10";
- char *sec_fname = "./secring.g10";
+ char *pub_fname = NULL;
+ char *sec_fname = NULL;
char *uid = NULL;
IOBUF pub_io = NULL;
IOBUF sec_io = NULL;
- PKT_public_cert *pkc = NULL;
+ KBNODE pub_root = NULL;
+ KBNODE sec_root = NULL;
PKT_secret_cert *skc = NULL;
- PKT_user_id *upkt = NULL;
DEK *dek = NULL;
int rc;
int algo;
@@ -315,8 +325,9 @@ generate_keypair()
tty_printf("Please select the algorithm to use:\n"
" (1) ElGamal is the suggested one.\n"
#ifdef HAVE_RSA_CIPHER
- " (2) RSA cannot be used inthe U.S.\n"
+ " (2) RSA cannot be used in the U.S.\n"
#endif
+ " (3) DSA can only be used for signatures.\n"
);
#endif
@@ -324,7 +335,11 @@ generate_keypair()
#ifdef TEST_ALGO
algo = TEST_ALGO;
#else
- answer = tty_get("Your selection? (1,2) ");
+ answer = tty_get("Your selection? (1"
+ #ifdef HAVE_RSA_CIPHER
+ ",2"
+ #endif
+ ",3) ");
tty_kill_prompt();
algo = *answer? atoi(answer): 1;
m_free(answer);
@@ -341,6 +356,11 @@ generate_keypair()
break;
}
#endif
+ else if( algo == 3 ) {
+ algo = PUBKEY_ALGO_DSA;
+ algo_name = "DSA";
+ break;
+ }
}
@@ -361,7 +381,9 @@ generate_keypair()
nbits = *answer? atoi(answer): 1024;
m_free(answer);
#endif
- if( nbits < 128 ) /* FIXME: change this to 768 */
+ if( algo == PUBKEY_ALGO_DSA && (nbits < 512 || nbits > 1024) )
+ tty_printf("DSA does only allow keysizes from 512 to 1024\n");
+ else if( nbits < 128 ) /* FIXME: change this to 768 */
tty_printf("keysize too small; please select a larger one\n");
else if( nbits > 2048 ) {
tty_printf("Keysizes larger than 2048 are not suggested, because "
@@ -381,7 +403,11 @@ generate_keypair()
break;
}
tty_printf("Requested keysize is %u bits\n", nbits );
- if( (nbits % 32) ) {
+ if( algo == PUBKEY_ALGO_DSA && (nbits % 64) ) {
+ nbits = ((nbits + 63) / 64) * 64;
+ tty_printf("rounded up to %u bits\n", nbits );
+ }
+ else if( (nbits % 32) ) {
nbits = ((nbits + 31) / 32) * 32;
tty_printf("rounded up to %u bits\n", nbits );
}
@@ -435,74 +461,103 @@ generate_keypair()
}
- /* now check wether we a are allowed to write the keyrings */
- if( !(rc=overwrite_filep( pub_fname )) ) {
- if( !(pub_io = iobuf_create( pub_fname )) )
- log_error("can't create %s: %s\n", pub_fname, strerror(errno) );
- else if( opt.verbose )
- log_info("writing to '%s'\n", pub_fname );
- }
- else if( rc != -1 ) {
- log_error("Oops: overwrite_filep(%s): %s\n", pub_fname, g10_errstr(rc) );
- m_free(uid);
- return;
- }
- else {
- m_free(uid);
- return;
- }
- if( !(rc=overwrite_filep( sec_fname )) ) {
- if( !(sec_io = iobuf_create( sec_fname )) )
- log_error("can't create %s: %s\n", sec_fname, strerror(errno) );
- else if( opt.verbose )
- log_info("writing to '%s'\n", sec_fname );
- }
- else if( rc != -1 ) {
- log_error("Oops: overwrite_filep(%s): %s\n", sec_fname, g10_errstr(rc) );
- m_free(uid);
- return;
- }
- else {
- iobuf_cancel(pub_io);
- m_free(uid);
- return;
+ /* now check wether we a are allowed to write to the keyrings */
+ pub_fname = make_filename("~/.g10", "pubring.g10", NULL );
+ sec_fname = make_filename("~/.g10", "secring.g10", NULL );
+ if( opt.verbose ) {
+ tty_printf("writing public certificate to '%s'\n", pub_fname );
+ tty_printf("writing secret certificate to '%s'\n", sec_fname );
}
- write_comment( pub_io, "#public key created by G10 pre-release " VERSION );
- write_comment( sec_io, "#secret key created by G10 pre-release " VERSION );
+ /* 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.
+ */
+ pub_root = make_comment_node("#created by G10 pre-release " VERSION );
+ sec_root = make_comment_node("#created by G10 pre-release " VERSION );
if( algo == PUBKEY_ALGO_ELGAMAL )
- rc = gen_elg(nbits, pub_io, sec_io, dek, &pkc, &skc);
+ rc = gen_elg(nbits, pub_root, sec_root, dek, &skc );
#ifdef HAVE_RSA_CIPHER
else if( algo == PUBKEY_ALGO_RSA )
- rc = gen_rsa(nbits, pub_io, sec_io, dek, &pkc, &skc);
+ rc = gen_rsa(nbits, pub_io, sec_io, dek, &skc );
#endif
+ else if( algo == PUBKEY_ALGO_DSA )
+ rc = gen_dsa(nbits, pub_root, sec_root, dek, &skc );
else
log_bug(NULL);
if( !rc )
- write_uid(pub_io, uid, &upkt );
+ write_uid(pub_root, uid );
+ if( !rc )
+ write_uid(sec_root, uid );
if( !rc )
- write_uid(sec_io, uid, NULL );
+ rc = write_selfsig(pub_root, pub_root, skc);
if( !rc )
- rc = write_selfsig(pub_io, pkc, upkt, skc );
+ rc = write_selfsig(sec_root, pub_root, skc);
- if( rc ) {
- iobuf_cancel(pub_io);
- iobuf_cancel(sec_io);
- tty_printf("Key generation failed: %s\n", g10_errstr(rc) );
- }
- else {
- iobuf_close(pub_io);
- iobuf_close(sec_io);
- tty_printf("public and secret key created and signed.\n" );
+ if( !rc ) {
+ KBPOS pub_kbpos;
+ KBPOS sec_kbpos;
+ int rc1 = -1;
+ int rc2 = -1;
+
+ /* we can now write the certificates */
+ /* FIXME: should we check wether the user-id already exists? */
+
+ if( get_keyblock_handle( pub_fname, &pub_kbpos ) ) {
+ if( add_keyblock_resource( pub_fname, 1 ) ) {
+ log_error("can add keyblock file '%s'\n", pub_fname );
+ rc = G10ERR_CREATE_FILE;
+ }
+ else if( get_keyblock_handle( pub_fname, &pub_kbpos ) ) {
+ log_error("can get keyblock handle for '%s'\n", pub_fname );
+ rc = G10ERR_CREATE_FILE;
+ }
+ }
+ if( rc )
+ ;
+ else if( get_keyblock_handle( sec_fname, &sec_kbpos ) ) {
+ if( add_keyblock_resource( sec_fname, 1 ) ) {
+ log_error("can add keyblock file '%s'\n", sec_fname );
+ rc = G10ERR_CREATE_FILE;
+ }
+ else if( get_keyblock_handle( sec_fname, &sec_kbpos ) ) {
+ log_error("can get keyblock handle for '%s'\n", sec_fname );
+ rc = G10ERR_CREATE_FILE;
+ }
+ }
+
+ if( rc )
+ ;
+ else if( (rc=rc1=lock_keyblock( &pub_kbpos )) )
+ log_error("can't lock public keyring: %s\n", g10_errstr(rc) );
+ else if( (rc=rc2=lock_keyblock( &sec_kbpos )) )
+ log_error("can't lock secret keyring: %s\n", g10_errstr(rc) );
+ else if( (rc=insert_keyblock( &pub_kbpos, pub_root )) )
+ log_error("can't write public key: %s\n", g10_errstr(rc) );
+ else if( (rc=insert_keyblock( &sec_kbpos, sec_root )) )
+ log_error("can't write secret key: %s\n", g10_errstr(rc) );
+ else {
+ tty_printf("public and secret key created and signed.\n" );
+ }
+
+ if( !rc1 )
+ unlock_keyblock( &pub_kbpos );
+ if( !rc2 )
+ unlock_keyblock( &sec_kbpos );
}
- if( pkc )
- free_public_cert( pkc );
- if( skc )
- free_secret_cert( skc );
- if( upkt )
- free_user_id( upkt );
+
+
+ if( rc )
+ tty_printf("Key generation failed: %s\n", g10_errstr(rc) );
+ release_kbnode( pub_root );
+ release_kbnode( sec_root );
+ if( skc ) /* the unprotected secret certificate */
+ free_secret_cert(skc);
m_free(uid);
m_free(dek);
+ m_free(pub_fname);
+ m_free(sec_fname);
}
diff --git a/g10/keyid.c b/g10/keyid.c
index e3a16d86b..307e28c61 100644
--- a/g10/keyid.c
+++ b/g10/keyid.c
@@ -33,6 +33,18 @@
#include "keydb.h"
+int
+pubkey_letter( int algo )
+{
+ switch( algo ) {
+ case PUBKEY_ALGO_RSA: return 'R' ;
+ case PUBKEY_ALGO_RSA_E: return 'r' ;
+ case PUBKEY_ALGO_RSA_S: return 's' ;
+ case PUBKEY_ALGO_ELGAMAL: return 'G' ;
+ case PUBKEY_ALGO_DSA: return 'D' ;
+ default: return '?';
+ }
+}
/****************
diff --git a/g10/main.h b/g10/main.h
index 8be922b8a..13e20a750 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -22,6 +22,7 @@
#include "types.h"
#include "iobuf.h"
#include "cipher.h"
+#include "keydb.h"
#define DEFAULT_CIPHER_ALGO CIPHER_ALGO_BLOWFISH
#define DEFAULT_PUBKEY_ALGO PUBKEY_ALGO_ELGAMAL
@@ -34,6 +35,7 @@ int encode_crypt( const char *filename, STRLIST remusr );
/*-- sign.c --*/
int sign_file( const char *filename, int detached, STRLIST locusr );
+int sign_key( const char *username, STRLIST locusr );
/*-- keygen.c --*/
void generate_keypair(void);
@@ -49,5 +51,7 @@ MPI encode_rmd160_value( byte *md, unsigned len, unsigned nbits );
MPI encode_md5_value( byte *md, unsigned len, unsigned nbits );
MPI encode_md_value( MD_HANDLE *md, unsigned nbits );
+/*-- comment.c --*/
+KBNODE make_comment_node( const char *s );
#endif /*G10_MAIN_H*/
diff --git a/g10/mainproc.c b/g10/mainproc.c
index a8b621289..8bee0de09 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -56,19 +56,6 @@ typedef struct {
static void list_node( CTX c, KBNODE node );
static void proc_tree( CTX c, KBNODE node );
-static int
-pubkey_letter( int algo )
-{
- switch( algo ) {
- case PUBKEY_ALGO_RSA: return 'R' ;
- case PUBKEY_ALGO_RSA_E: return 'r' ;
- case PUBKEY_ALGO_RSA_S: return 's' ;
- case PUBKEY_ALGO_ELGAMAL: return 'G' ;
- case PUBKEY_ALGO_DSA: return 'D' ;
- default: return '?';
- }
-}
-
static void
release_cert( CTX c )
@@ -509,7 +496,6 @@ proc_packets( IOBUF a )
CTX c = m_alloc_clear( sizeof *c );
PACKET *pkt = m_alloc( sizeof *pkt );
int rc, result;
- char *ustr;
int lvl0, lvl1;
u32 keyid[2];
int newpkt;
diff --git a/g10/options.h b/g10/options.h
index a23412fc8..3be6c92c3 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -34,7 +34,7 @@ struct {
int cache_all;
int fingerprint; /* list fingerprints */
int list_sigs; /* list signatures */
- int reserved4;
+ int no_armor;
int reserved5;
int reserved6;
int reserved7;
diff --git a/g10/ringedit.c b/g10/ringedit.c
index e4380c3d1..10aa7c947 100644
--- a/g10/ringedit.c
+++ b/g10/ringedit.c
@@ -60,9 +60,10 @@ struct resource_table_struct {
char *fname;
IOBUF iobuf;
};
+typedef struct resource_table_struct RESTBL;
#define MAX_RESOURCES 10
-static struct resource_table_struct resource_table[MAX_RESOURCES];
+static RESTBL resource_table[MAX_RESOURCES];
static int keyring_search( PACKET *pkt, KBPOS *kbpos, IOBUF iobuf );
@@ -72,14 +73,14 @@ static int keyring_delete( KBPOS *kbpos );
-static int
+static RESTBL *
check_pos( KBPOS *kbpos )
{
if( kbpos->resno < 0 || kbpos->resno >= MAX_RESOURCES )
- return G10ERR_GENERAL;
+ return NULL;
if( !resource_table[kbpos->resno].used )
- return G10ERR_GENERAL;
- return 0;
+ return NULL;
+ return resource_table + kbpos->resno;
}
@@ -92,7 +93,7 @@ check_pos( KBPOS *kbpos )
* Register a resource (which currently may ionly be a keyring file).
*/
int
-add_keyblock_resource( const char *filename )
+add_keyblock_resource( const char *filename, int force )
{
IOBUF iobuf;
int i;
@@ -104,7 +105,7 @@ add_keyblock_resource( const char *filename )
return G10ERR_RESOURCE_LIMIT;
iobuf = iobuf_open( filename );
- if( !iobuf )
+ if( !iobuf && !force )
return G10ERR_OPEN_FILE;
resource_table[i].used = 1;
resource_table[i].fname = m_strdup(filename);
@@ -170,6 +171,31 @@ search_keyblock( PACKET *pkt, KBPOS *kbpos )
}
+/****************
+ * Combined function to search for a username and get the position
+ * of the keyblock.
+ */
+int
+search_keyblock_byname( KBPOS *kbpos, const char *username )
+{
+ PACKET pkt;
+ PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
+ int rc;
+
+ rc = get_pubkey_byname( pkc, username );
+ if( rc ) {
+ free_public_cert(pkc);
+ return rc;
+ }
+
+ init_packet( &pkt );
+ pkt.pkttype = PKT_PUBLIC_CERT;
+ pkt.pkt.public_cert = pkc;
+ rc = search_keyblock( &pkt, kbpos );
+ free_public_cert(pkc);
+ return rc;
+}
+
/****************
* Lock the keyblock; wait until it's available
@@ -182,22 +208,19 @@ lock_keyblock( KBPOS *kbpos )
{
int rc;
- if( (rc=check_pos(kbpos)) )
- return rc;
+ if( !check_pos(kbpos) )
+ return G10ERR_GENERAL;
return 0;
}
/****************
* Release a lock on a keyblock
*/
-int
+void
unlock_keyblock( KBPOS *kbpos )
{
- int rc;
-
- if( (rc=check_pos(kbpos)) )
- return rc;
- return 0;
+ if( !check_pos(kbpos) )
+ log_bug(NULL);
}
/****************
@@ -206,10 +229,8 @@ unlock_keyblock( KBPOS *kbpos )
int
read_keyblock( KBPOS *kbpos, KBNODE *ret_root )
{
- int rc;
-
- if( (rc=check_pos(kbpos)) )
- return rc;
+ if( !check_pos(kbpos) )
+ return G10ERR_GENERAL;
return keyring_read( kbpos, ret_root );
}
@@ -222,8 +243,8 @@ insert_keyblock( KBPOS *kbpos, KBNODE root )
{
int rc;
- if( (rc=check_pos(kbpos)) )
- return rc;
+ if( !check_pos(kbpos) )
+ return G10ERR_GENERAL;
rc = keyring_insert( kbpos, root );
@@ -241,8 +262,8 @@ delete_keyblock( KBPOS *kbpos )
{
int rc;
- if( (rc=check_pos(kbpos)) )
- return rc;
+ if( !check_pos(kbpos) )
+ return G10ERR_GENERAL;
rc = keyring_delete( kbpos );
@@ -358,13 +379,26 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root )
{
PACKET *pkt;
int rc;
+ RESTBL *rentry;
KBNODE root = NULL;
KBNODE node, n1, n2;
IOBUF a;
- if( (rc=check_pos(kbpos)) )
- return rc;
- a = resource_table[kbpos->resno].iobuf;
+ if( !(rentry=check_pos(kbpos)) )
+ return G10ERR_GENERAL;
+
+ a = iobuf_open( rentry->fname );
+ if( !a ) {
+ log_error("can't open '%s'\n", rentry->fname );
+ return G10ERR_OPEN_FILE;
+ }
+
+ if( iobuf_seek( a, kbpos->offset ) ) {
+ log_error("can't seek to %lu: %s\n", kbpos->offset, g10_errstr(rc));
+ iobuf_close(a);
+ return G10ERR_KEYRING_OPEN;
+ }
+
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
@@ -377,7 +411,7 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root )
case PKT_PUBLIC_CERT:
case PKT_SECRET_CERT:
if( root )
- break;
+ goto ready;
root = new_kbnode( pkt );
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
@@ -386,8 +420,8 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root )
case PKT_USER_ID:
if( !root ) {
log_error("read_keyblock: orphaned user id\n" );
- rc = G10ERR_INV_KEYRING; /* or wron kbpos */
- break;
+ rc = G10ERR_INV_KEYRING; /* or wrong kbpos */
+ goto ready;
}
/* append the user id */
node = new_kbnode( pkt );
@@ -434,6 +468,7 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root )
break;
}
}
+ ready:
kbpos->last_block = rc == -1; /* flag, that this is the last block */
if( rc == -1 && root )
rc = 0;
@@ -446,14 +481,49 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root )
}
free_packet( pkt );
m_free( pkt );
+ iobuf_close(a);
return rc;
}
+/****************
+ * Insert the keyblock described by ROOT into the keyring described
+ * by KBPOS. This actually appends the data to the keyfile.
+ */
static int
keyring_insert( KBPOS *kbpos, KBNODE root )
{
- return -1;
+ RESTBL *rentry;
+ IOBUF fp;
+ KBNODE kbctx, node;
+ int rc;
+
+ if( !(rentry = check_pos( kbpos )) )
+ return G10ERR_GENERAL;
+
+ /* FIXME: we must close the file if it's already open, due to
+ * 2 reasons:
+ * - cannot open the same file twice on DOSish OSes
+ * - must sync with iobufs somehow
+ */
+ /* open the file for append */
+ fp = iobuf_append( rentry->fname );
+ if( !fp ) {
+ log_error("can't append to '%s'\n", rentry->fname );
+ return G10ERR_OPEN_FILE;
+ }
+
+ kbctx=NULL;
+ while( (node = walk_kbtree( root, &kbctx )) ) {
+ if( (rc = build_packet( fp, node->pkt )) ) {
+ log_error("build_packet(%d) failed: %s\n",
+ node->pkt->pkttype, g10_errstr(rc) );
+ return G10ERR_WRITE_FILE;
+ }
+ }
+ iobuf_close(fp);
+
+ return 0;
}
static int
diff --git a/g10/seskey.c b/g10/seskey.c
index cf34295e5..325234c45 100644
--- a/g10/seskey.c
+++ b/g10/seskey.c
@@ -49,7 +49,7 @@ make_session_key( DEK *dek )
/****************
* Encode the session key. NBITS is the number of bits which should be used
- * for packing teh session key.
+ * for packing the session key.
* returns: A mpi with the session key (caller must free)
*/
MPI