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

added some stuff for signing keys

This commit is contained in:
Werner Koch 1997-12-16 19:15:09 +00:00
parent 68ea0f4353
commit 15426c6d96
27 changed files with 750 additions and 267 deletions

View file

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

View file

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

View file

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

View file

@ -56,6 +56,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
*/
@ -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;
}

View file

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

View file

@ -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_io, uid, NULL );
write_uid(sec_root, uid );
if( !rc )
rc = write_selfsig(pub_io, pkc, upkt, skc );
rc = write_selfsig(pub_root, pub_root, skc);
if( !rc )
rc = write_selfsig(sec_root, pub_root, skc);
if( rc ) {
iobuf_cancel(pub_io);
iobuf_cancel(sec_io);
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( rc )
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( pkc )
free_public_cert( pkc );
if( skc )
free_secret_cert( skc );
if( upkt )
free_user_id( upkt );
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);
}

View file

@ -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 '?';
}
}
/****************

View file

@ -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*/

View file

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

View file

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

View file

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

View file

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