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

26
INSTALL
View File

@ -0,0 +1,26 @@
1) Configure for your machine:
./configure
or use
./configure --enable-m-debug
to ebanle the integrated malloc debugging stuff.
2) Run make:
make
3) Install
make install
4) You end up with a binary "g10" in /usr/local/bin

50
README
View File

@ -0,0 +1,50 @@
G10 - The GNU Enryption and Signing Tool
------------------------------------------
THIS IS VERSION IS ONLY a TEST VERSION ! YOU SHOULD NOT
USE IT FOR OTHER PURPOSES THAN EVALUATING THE CURRENT CODE.
* The data format may change in the next version!
* The code to generate keys is not secure!
* Some features are not implemented
I provide this version as a reality check to start discussion.
Please subscribe to g10@net.lut.ac.uk be sending a mail with
the word "subscribe" in the body to "g10-request@net.lut.ac.uk".
See the file COPYING for copyright and warranty information.
Due to the fact that G10 does not use use any patented algorithm,
it cannot be compatible to old PGP versions, because those use
IDEA (which is worldwide patented) and RSA (which is patented in
the United States until Sep 20, 2000). I'm sorry about this, but
this is the world we have created (e.g. by using propiertary software).
Because the OpenPGP standard is still a draft, G10 is not yet
compatible to it (or PGP 5) - but it will. The data structures
used are compatible with PGP 2.x, so it can parse an list such files
and PGP should be able to parse data created by G10 and complain
about unsupported alogorithms.
The default algorithms used by G10 are ElGamal for public-key
encryption and signing; Blowfish with a 160 bit key for protecting
the secret-key components, conventional and session encryption;
RIPE MD-160 to create message digest. DSA, SHA-1 and CAST are
also implemented, but not used on default. I decided not
to use DSA as default signing algorithm, cecause it allows only for
1024 bit keys and this may be not enough in a couple of years.
Key generation takes a long time and should be improved!

12
TODO
View File

@ -8,14 +8,10 @@
* keyring editing * keyring editing
* add trust stuff * add trust stuff
* make ttyio.c work (hide passwords etc..) * make ttyio.c work (hide passwords etc..)
* add option file handling.
* use correct ASN values for DEK encoding * use correct ASN values for DEK encoding
* add checking of armor trailers * add checking of armor trailers
* add real secure memory * add real secure memory
* look for a way to reuse RSA signatures * look for a way to reuse RSA signatures
* find a way to remove the armor filter after it
has detected, that the data is not armored.
* Use the Chinese Remainder Theorem to speed up RSA calculations.
* remove all "Fixmes" * remove all "Fixmes"
* speed up the RIPE-MD-160 * speed up the RIPE-MD-160
* add signal handling * add signal handling
@ -33,3 +29,11 @@
* complete cipher/cast.c * complete cipher/cast.c
* complete cipher/dsa.c * complete cipher/dsa.c
* define a standard way to specify keyid/userid and other stuff
to identify a user. We could look at the first character and
say: If it's a digit, a keyid follows (need to add a zero in
case the keyid starts with A..F); if it is a left angle bracket,
this is a email address and should be used, all others are substrings
of the userid.
[can be handles in get_pubkey_by_name()]

View File

@ -24,6 +24,6 @@ cipher_SOURCES = blowfish.c \
md.c \ md.c \
smallprime.c smallprime.c
cipher_LIBADD = rsa.o ##cipher_LIBADD = rsa.o

View File

@ -60,8 +60,6 @@ cipher_SOURCES = blowfish.c \
dsa.c \ dsa.c \
md.c \ md.c \
smallprime.c smallprime.c
cipher_LIBADD = rsa.o
mkinstalldirs = $(top_srcdir)/scripts/mkinstalldirs mkinstalldirs = $(top_srcdir)/scripts/mkinstalldirs
CONFIG_HEADER = ../config.h CONFIG_HEADER = ../config.h
LIBRARIES = $(noinst_LIBRARIES) LIBRARIES = $(noinst_LIBRARIES)
@ -80,6 +78,7 @@ LIBS = @LIBS@
COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
LINK = $(CC) $(LDFLAGS) -o $@ LINK = $(CC) $(LDFLAGS) -o $@
cipher_LIBADD =
cipher_OBJECTS = blowfish.o elgamal.o gost.o md5.o primegen.o random.o \ cipher_OBJECTS = blowfish.o elgamal.o gost.o md5.o primegen.o random.o \
rmd160.o sha1.o dsa.o md.o smallprime.o rmd160.o sha1.o dsa.o md.o smallprime.o
EXTRA_cipher_SOURCES = EXTRA_cipher_SOURCES =

View File

@ -22,21 +22,20 @@ fi
CFLAGS="-g" CFLAGS="-g"
dnl dnl
AC_CANONICAL_HOST AC_CANONICAL_SYSTEM
AC_MSG_CHECKING(cached information) AC_MSG_CHECKING(cached information)
hostcheck="$host" hostcheck="$target"
AC_CACHE_VAL(ac_cv_mpi_hostcheck, [ ac_cv_mpi_hostcheck="$hostcheck" ]) AC_CACHE_VAL(ac_cv_mpi_hostcheck, [ ac_cv_mpi_hostcheck="$hostcheck" ])
if test "$ac_cv_mpi_hostcheck" != "$hostcheck"; then if test "$ac_cv_mpi_hostcheck" != "$hostcheck"; then
AC_MSG_RESULT(changed) AC_MSG_RESULT(changed)
AC_MSG_WARN(config.cache exists!) AC_MSG_WARN(config.cache exists!)
AC_MSG_ERROR(you must do 'make distclean' first to compile for AC_MSG_ERROR(you must do 'make distclean' first to compile for
different host or different parameters.) different target or different parameters.)
else else
AC_MSG_RESULT(ok) AC_MSG_RESULT(ok)
fi fi
dnl Checks for programs. dnl Checks for programs.
AC_PROG_MAKE_SET AC_PROG_MAKE_SET
@ -71,8 +70,12 @@ AC_CHECK_FUNCS(strerror strtol strtoul)
dnl setup assembler stuff dnl setup assembler stuff
if test -f ./mpi/config.links ; then
. ./mpi/config.links
AC_LINK_FILES( ${mpi_ln_src}, ${mpi_ln_dst} )
else
AC_MSG_ERROR([mpi/config.links missing!])
fi
@ -91,6 +94,7 @@ fi
AC_SUBST(add_cipher_SOURCES) AC_SUBST(add_cipher_SOURCES)
AC_OUTPUT([ Makefile scripts/Makefile util/Makefile mpi/Makefile \ AC_OUTPUT([ Makefile scripts/Makefile util/Makefile mpi/Makefile \
mpi/generic/Makefile mpi/i386/Makefile \
cipher/Makefile \ cipher/Makefile \
include/Makefile \ include/Makefile \
g10/Makefile tools/Makefile ], g10/Makefile tools/Makefile ],

View File

@ -218,7 +218,7 @@ encode_crypt( const char *filename, STRLIST remusr )
pkc = m_alloc_clear( sizeof *pkc ); pkc = m_alloc_clear( sizeof *pkc );
pkc->pubkey_algo = DEFAULT_PUBKEY_ALGO; 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; last_rc = rc;
log_error("skipped '%s': %s\n", remusr->d, g10_errstr(rc) ); log_error("skipped '%s': %s\n", remusr->d, g10_errstr(rc) );
continue; continue;

View File

@ -125,20 +125,21 @@ main( int argc, char **argv )
{ 510, "debug" ,4|16, "set debugging flags" }, { 510, "debug" ,4|16, "set debugging flags" },
{ 511, "debug-all" ,0, "enable full debugging"}, { 511, "debug-all" ,0, "enable full debugging"},
{ 512, "cache-all" ,0, "hold everything in memory"}, { 512, "cache-all" ,0, "hold everything in memory"},
{ 513, "gen-prime" , 1, "\rgenerate a prime of length n" }, { 513, "gen-prime" , 1, "\r" },
{ 514, "test" , 0, "\rdevelopment usage" }, { 514, "test" , 0, "\r" },
{ 515, "change-passphrase", 0, "change the passphrase of your secret keyring"}, { 515, "change-passphrase", 0, "change the passphrase of your secret keyring"},
{ 515, "fingerprint", 0, "show the fingerprints"}, { 515, "fingerprint", 0, "show the fingerprints"},
{ 516, "print-mds" , 0, "print all message digests"}, { 516, "print-mds" , 0, "print all message digests"},
{ 517, "secret-keyring" ,2, "add this secret keyring to the list" }, { 517, "secret-keyring" ,2, "add this secret keyring to the list" },
{ 518, "config" , 2, "use this config file" }, { 518, "config" , 2, "use this config file" },
{ 519, "no-armor", 0, "\r"},
{0} }; {0} };
ARGPARSE_ARGS pargs; ARGPARSE_ARGS pargs;
IOBUF a; IOBUF a;
int rc; int rc;
enum { aNull, aSym, aStore, aEncr, aPrimegen, aKeygen, aSign, aSignEncr, enum { aNull, aSym, aStore, aEncr, aPrimegen, aKeygen, aSign, aSignEncr,
aTest, aPrintMDs, aTest, aPrintMDs, aSignKey,
} action = aNull; } action = aNull;
int orig_argc; int orig_argc;
char **orig_argv; char **orig_argv;
@ -189,7 +190,7 @@ main( int argc, char **argv )
configfp = fopen( configname, "r" ); configfp = fopen( configname, "r" );
if( !configfp ) { if( !configfp ) {
if( default_config ) { if( default_config ) {
if( parse_verbose ) if( parse_verbose > 1 )
log_info("note: no default option file '%s'\n", configname ); log_info("note: no default option file '%s'\n", configname );
} }
else else
@ -197,7 +198,7 @@ main( int argc, char **argv )
configname, strerror(errno) ); configname, strerror(errno) );
m_free(configname); configname = NULL; m_free(configname); configname = NULL;
} }
if( parse_verbose ) if( parse_verbose > 1 )
log_info("reading options from '%s'\n", configname ); log_info("reading options from '%s'\n", configname );
default_config = 0; default_config = 0;
} }
@ -209,7 +210,7 @@ main( int argc, char **argv )
opt.list_sigs=1; opt.list_sigs=1;
break; break;
case 'z': opt.compress = pargs.r.ret_int; 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 'c': action = aSym; break;
case 'o': opt.outfile = pargs.r.ret_str; case 'o': opt.outfile = pargs.r.ret_str;
if( opt.outfile[0] == '-' && !opt.outfile[1] ) if( opt.outfile[0] == '-' && !opt.outfile[1] )
@ -235,6 +236,7 @@ main( int argc, char **argv )
case 501: opt.answer_yes = 1; break; case 501: opt.answer_yes = 1; break;
case 502: opt.answer_no = 1; break; case 502: opt.answer_no = 1; break;
case 503: action = aKeygen; break; case 503: action = aKeygen; break;
case 506: action = aSignKey; break;
case 507: action = aStore; break; case 507: action = aStore; break;
case 508: opt.check_sigs = 1; opt.list_sigs = 1; break; case 508: opt.check_sigs = 1; opt.list_sigs = 1; break;
case 509: add_keyring(pargs.r.ret_str); nrings++; break; case 509: add_keyring(pargs.r.ret_str); nrings++; break;
@ -254,6 +256,7 @@ main( int argc, char **argv )
goto next_pass; goto next_pass;
} }
break; break;
case 519: opt.no_armor=1; opt.armor=0; break;
default : errors++; pargs.err = configfp? 1:2; break; default : errors++; pargs.err = configfp? 1:2; break;
} }
} }
@ -270,7 +273,7 @@ main( int argc, char **argv )
set_debug(); set_debug();
if( opt.verbose > 1 ) if( opt.verbose > 1 )
set_packet_list_mode(1); set_packet_list_mode(1);
if( !opt.batch && isatty(fileno(stdin)) ) { if( opt.verbose && isatty(fileno(stdin)) ) {
if( *(s=strusage(10)) ) if( *(s=strusage(10)) )
fputs(s, stderr); fputs(s, stderr);
if( *(s=strusage(30)) ) if( *(s=strusage(30)) )
@ -278,11 +281,14 @@ main( int argc, char **argv )
} }
if( !sec_nrings ) { /* add default secret rings */ 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 */ if( !nrings ) { /* add default ring */
add_keyring("../keys/ring.pgp"); char *p = make_filename("~/.g10", "pubring.g10", NULL );
add_keyring("../keys/pubring.g10"); add_keyring(p);
m_free(p);
} }
if( argc ) { if( argc ) {
@ -323,10 +329,21 @@ main( int argc, char **argv )
log_error("sign_file('%s'): %s\n", fname_print, g10_errstr(rc) ); log_error("sign_file('%s'): %s\n", fname_print, g10_errstr(rc) );
break; break;
case aSignEncr: /* sign and encrypt the given file */ case aSignEncr: /* sign and encrypt the given file */
usage(1); /* FIXME */ usage(1); /* FIXME */
break; 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: case aPrimegen:
if( argc ) if( argc )
usage(1); usage(1);
@ -356,9 +373,11 @@ main( int argc, char **argv )
usage(1); usage(1);
if( !(a = iobuf_open(fname)) ) if( !(a = iobuf_open(fname)) )
log_fatal("can't open '%s'\n", fname_print); log_fatal("can't open '%s'\n", fname_print);
/* push the armor filter, so it can peek at the input data */ if( !opt.no_armor ) {
memset( &afx, 0, sizeof afx); /* push the armor filter, so it can peek at the input data */
iobuf_push_filter( a, armor_filter, &afx ); memset( &afx, 0, sizeof afx);
iobuf_push_filter( a, armor_filter, &afx );
}
proc_packets( a ); proc_packets( a );
iobuf_close(a); iobuf_close(a);
break; break;

View File

@ -83,9 +83,9 @@ add_keyring( const char *name )
* combine it with the keyblock stuff from ringedit.c * combine it with the keyblock stuff from ringedit.c
* For now we will simple add the filename as keyblock resource * For now we will simple add the filename as keyblock resource
*/ */
rc = add_keyblock_resource( name ); rc = add_keyblock_resource( name, 0 );
if( rc ) if( rc )
log_error("keyblock resource '%s': %s\n", name, rc ); log_error("keyblock resource '%s': %s\n", name, g10_errstr(rc) );
} }
void void
@ -245,7 +245,7 @@ get_pubkey( PKT_public_cert *pkc, u32 *keyid )
* a pubkey with that algo. * a pubkey with that algo.
*/ */
int 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 internal = 0;
int rc = 0; int rc = 0;
@ -304,7 +304,7 @@ get_seckey( PKT_secret_cert *skc, u32 *keyid )
* If NAME is NULL use the default certificate * If NAME is NULL use the default certificate
*/ */
int 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; STRLIST sl;
int rc=0; 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 /* get the secret key (this may prompt for a passprase to
* unlock the secret key * unlock the secret key
*/ */
if( (rc = check_secret_key( skc )) ) if( unprotect )
goto leave; if( (rc = check_secret_key( skc )) )
goto leave;
leave: leave:
return rc; 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 * 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_public_cert( PKT_public_cert *pkc );
void cache_user_id( PKT_user_id *uid, u32 *keyid ); void cache_user_id( PKT_user_id *uid, u32 *keyid );
int get_pubkey( PKT_public_cert *pkc, 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( 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_string( u32 *keyid );
char*get_user_id( u32 *keyid, size_t *rn ); char*get_user_id( u32 *keyid, size_t *rn );
/*-- keyid.c --*/ /*-- keyid.c --*/
int pubkey_letter( int algo );
u32 keyid_from_skc( PKT_secret_cert *skc, u32 *keyid ); u32 keyid_from_skc( PKT_secret_cert *skc, u32 *keyid );
u32 keyid_from_pkc( PKT_public_cert *pkc, u32 *keyid ); u32 keyid_from_pkc( PKT_public_cert *pkc, u32 *keyid );
u32 keyid_from_sig( PKT_signature *sig, 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.c --*/
KBNODE new_kbnode( PACKET *pkt ); KBNODE new_kbnode( PACKET *pkt );
void release_kbnode( KBNODE n ); 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 find_kbparent( KBNODE root, KBNODE node );
KBNODE walk_kbtree( KBNODE root, KBNODE *context );
/*-- ringedit.c --*/ /*-- 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 get_keyblock_handle( const char *filename, KBPOS *kbpos );
int search_keyblock( PACKET *pkt, KBPOS *kbpos ); int search_keyblock( PACKET *pkt, KBPOS *kbpos );
int search_keyblock_byname( KBPOS *kbpos, const char *username );
int lock_keyblock( KBPOS *kbpos ); int lock_keyblock( KBPOS *kbpos );
int unlock_keyblock( KBPOS *kbpos ); void unlock_keyblock( KBPOS *kbpos );
int read_keyblock( KBPOS *kbpos, KBNODE *ret_root ); int read_keyblock( KBPOS *kbpos, KBNODE *ret_root );
int insert_keyblock( KBPOS *kbpos, KBNODE root ); int insert_keyblock( KBPOS *kbpos, KBNODE root );
int delete_keyblock( KBPOS *kbpos ); int delete_keyblock( KBPOS *kbpos );

View File

@ -30,6 +30,7 @@
#include "cipher.h" #include "cipher.h"
#include "ttyio.h" #include "ttyio.h"
#include "options.h" #include "options.h"
#include "keydb.h"
#if 0 #if 0
#define TEST_ALGO 1 #define TEST_ALGO 1
@ -88,52 +89,128 @@ checksum_mpi( MPI a )
static void 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); size_t n = strlen(s);
int rc;
pkt.pkttype = PKT_USER_ID; pkt->pkttype = PKT_USER_ID;
pkt.pkt.user_id = m_alloc( sizeof *pkt.pkt.user_id + n - 1 ); pkt->pkt.user_id = m_alloc( sizeof *pkt->pkt.user_id + n - 1 );
pkt.pkt.user_id->len = n; pkt->pkt.user_id->len = n;
strcpy(pkt.pkt.user_id->name, s); strcpy(pkt->pkt.user_id->name, s);
if( (rc = build_packet( out, &pkt )) ) add_kbnode( root, new_kbnode( 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 );
} }
static int static int
write_selfsig( IOBUF out, PKT_public_cert *pkc, PKT_user_id *uid, write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_cert *skc )
PKT_secret_cert *skc )
{ {
PACKET pkt; PACKET *pkt;
PKT_signature *sig; PKT_signature *sig;
PKT_user_id *uid;
int rc=0; int rc=0;
KBNODE kbctx, node;
PKT_public_cert *pkc;
if( opt.verbose ) if( opt.verbose )
log_info("writing self signature\n"); 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 ); rc = make_keysig_packet( &sig, pkc, uid, skc, 0x13, DIGEST_ALGO_RMD160 );
if( rc ) { if( rc ) {
log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) ); log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) );
return rc; return rc;
} }
pkt.pkttype = PKT_SIGNATURE; pkt = m_alloc_clear( sizeof *pkt );
pkt.pkt.signature = sig; pkt->pkttype = PKT_SIGNATURE;
if( (rc = build_packet( out, &pkt )) ) pkt->pkt.signature = sig;
log_error("build_packet(signature) failed: %s\n", g10_errstr(rc) ); add_kbnode( root, new_kbnode( pkt ) );
free_packet( &pkt );
return rc; 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 #ifdef HAVE_RSA_CIPHER
static int static int
gen_rsa(unsigned nbits, IOBUF pub_io, IOBUF sec_io, DEK *dek, 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*/ #endif /*HAVE_RSA_CIPHER*/
static int static int
gen_elg(unsigned nbits, IOBUF pub_io, IOBUF sec_io, DEK *dek, gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
PKT_public_cert **ret_pkc, PKT_secret_cert **ret_skc ) PKT_secret_cert **ret_skc )
{ {
int rc; return G10ERR_GENERAL;
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;
} }
@ -295,14 +305,14 @@ generate_keypair()
{ {
char *answer; char *answer;
unsigned nbits; unsigned nbits;
char *pub_fname = "./pubring.g10"; char *pub_fname = NULL;
char *sec_fname = "./secring.g10"; char *sec_fname = NULL;
char *uid = NULL; char *uid = NULL;
IOBUF pub_io = NULL; IOBUF pub_io = NULL;
IOBUF sec_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_secret_cert *skc = NULL;
PKT_user_id *upkt = NULL;
DEK *dek = NULL; DEK *dek = NULL;
int rc; int rc;
int algo; int algo;
@ -315,8 +325,9 @@ generate_keypair()
tty_printf("Please select the algorithm to use:\n" tty_printf("Please select the algorithm to use:\n"
" (1) ElGamal is the suggested one.\n" " (1) ElGamal is the suggested one.\n"
#ifdef HAVE_RSA_CIPHER #ifdef HAVE_RSA_CIPHER
" (2) RSA cannot be used inthe U.S.\n" " (2) RSA cannot be used in the U.S.\n"
#endif #endif
" (3) DSA can only be used for signatures.\n"
); );
#endif #endif
@ -324,7 +335,11 @@ generate_keypair()
#ifdef TEST_ALGO #ifdef TEST_ALGO
algo = TEST_ALGO; algo = TEST_ALGO;
#else #else
answer = tty_get("Your selection? (1,2) "); answer = tty_get("Your selection? (1"
#ifdef HAVE_RSA_CIPHER
",2"
#endif
",3) ");
tty_kill_prompt(); tty_kill_prompt();
algo = *answer? atoi(answer): 1; algo = *answer? atoi(answer): 1;
m_free(answer); m_free(answer);
@ -341,6 +356,11 @@ generate_keypair()
break; break;
} }
#endif #endif
else if( algo == 3 ) {
algo = PUBKEY_ALGO_DSA;
algo_name = "DSA";
break;
}
} }
@ -361,7 +381,9 @@ generate_keypair()
nbits = *answer? atoi(answer): 1024; nbits = *answer? atoi(answer): 1024;
m_free(answer); m_free(answer);
#endif #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"); tty_printf("keysize too small; please select a larger one\n");
else if( nbits > 2048 ) { else if( nbits > 2048 ) {
tty_printf("Keysizes larger than 2048 are not suggested, because " tty_printf("Keysizes larger than 2048 are not suggested, because "
@ -381,7 +403,11 @@ generate_keypair()
break; break;
} }
tty_printf("Requested keysize is %u bits\n", nbits ); 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; nbits = ((nbits + 31) / 32) * 32;
tty_printf("rounded up to %u bits\n", nbits ); 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 */ /* now check wether we a are allowed to write to the keyrings */
if( !(rc=overwrite_filep( pub_fname )) ) { pub_fname = make_filename("~/.g10", "pubring.g10", NULL );
if( !(pub_io = iobuf_create( pub_fname )) ) sec_fname = make_filename("~/.g10", "secring.g10", NULL );
log_error("can't create %s: %s\n", pub_fname, strerror(errno) ); if( opt.verbose ) {
else if( opt.verbose ) tty_printf("writing public certificate to '%s'\n", pub_fname );
log_info("writing to '%s'\n", pub_fname ); tty_printf("writing secret certificate to '%s'\n", sec_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;
} }
write_comment( pub_io, "#public key created by G10 pre-release " VERSION ); /* we create the packets as a tree of kbnodes. Because the structure
write_comment( sec_io, "#secret key created by G10 pre-release " VERSION ); * 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 ) 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 #ifdef HAVE_RSA_CIPHER
else if( algo == PUBKEY_ALGO_RSA ) 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 #endif
else if( algo == PUBKEY_ALGO_DSA )
rc = gen_dsa(nbits, pub_root, sec_root, dek, &skc );
else else
log_bug(NULL); log_bug(NULL);
if( !rc ) if( !rc )
write_uid(pub_io, uid, &upkt ); write_uid(pub_root, uid );
if( !rc ) if( !rc )
write_uid(sec_io, uid, NULL ); write_uid(sec_root, uid );
if( !rc ) 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 ) { if( !rc ) {
iobuf_cancel(pub_io); KBPOS pub_kbpos;
iobuf_cancel(sec_io); 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) ); tty_printf("Key generation failed: %s\n", g10_errstr(rc) );
} release_kbnode( pub_root );
else { release_kbnode( sec_root );
iobuf_close(pub_io); if( skc ) /* the unprotected secret certificate */
iobuf_close(sec_io); free_secret_cert(skc);
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 );
m_free(uid); m_free(uid);
m_free(dek); m_free(dek);
m_free(pub_fname);
m_free(sec_fname);
} }

View File

@ -33,6 +33,18 @@
#include "keydb.h" #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 "types.h"
#include "iobuf.h" #include "iobuf.h"
#include "cipher.h" #include "cipher.h"
#include "keydb.h"
#define DEFAULT_CIPHER_ALGO CIPHER_ALGO_BLOWFISH #define DEFAULT_CIPHER_ALGO CIPHER_ALGO_BLOWFISH
#define DEFAULT_PUBKEY_ALGO PUBKEY_ALGO_ELGAMAL #define DEFAULT_PUBKEY_ALGO PUBKEY_ALGO_ELGAMAL
@ -34,6 +35,7 @@ int encode_crypt( const char *filename, STRLIST remusr );
/*-- sign.c --*/ /*-- sign.c --*/
int sign_file( const char *filename, int detached, STRLIST locusr ); int sign_file( const char *filename, int detached, STRLIST locusr );
int sign_key( const char *username, STRLIST locusr );
/*-- keygen.c --*/ /*-- keygen.c --*/
void generate_keypair(void); 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_md5_value( byte *md, unsigned len, unsigned nbits );
MPI encode_md_value( MD_HANDLE *md, unsigned nbits ); MPI encode_md_value( MD_HANDLE *md, unsigned nbits );
/*-- comment.c --*/
KBNODE make_comment_node( const char *s );
#endif /*G10_MAIN_H*/ #endif /*G10_MAIN_H*/

View File

@ -56,19 +56,6 @@ typedef struct {
static void list_node( CTX c, KBNODE node ); static void list_node( CTX c, KBNODE node );
static void proc_tree( 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 static void
release_cert( CTX c ) release_cert( CTX c )
@ -509,7 +496,6 @@ proc_packets( IOBUF a )
CTX c = m_alloc_clear( sizeof *c ); CTX c = m_alloc_clear( sizeof *c );
PACKET *pkt = m_alloc( sizeof *pkt ); PACKET *pkt = m_alloc( sizeof *pkt );
int rc, result; int rc, result;
char *ustr;
int lvl0, lvl1; int lvl0, lvl1;
u32 keyid[2]; u32 keyid[2];
int newpkt; int newpkt;

View File

@ -34,7 +34,7 @@ struct {
int cache_all; int cache_all;
int fingerprint; /* list fingerprints */ int fingerprint; /* list fingerprints */
int list_sigs; /* list signatures */ int list_sigs; /* list signatures */
int reserved4; int no_armor;
int reserved5; int reserved5;
int reserved6; int reserved6;
int reserved7; int reserved7;

View File

@ -60,9 +60,10 @@ struct resource_table_struct {
char *fname; char *fname;
IOBUF iobuf; IOBUF iobuf;
}; };
typedef struct resource_table_struct RESTBL;
#define MAX_RESOURCES 10 #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 ); 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 ) check_pos( KBPOS *kbpos )
{ {
if( kbpos->resno < 0 || kbpos->resno >= MAX_RESOURCES ) if( kbpos->resno < 0 || kbpos->resno >= MAX_RESOURCES )
return G10ERR_GENERAL; return NULL;
if( !resource_table[kbpos->resno].used ) if( !resource_table[kbpos->resno].used )
return G10ERR_GENERAL; return NULL;
return 0; return resource_table + kbpos->resno;
} }
@ -92,7 +93,7 @@ check_pos( KBPOS *kbpos )
* Register a resource (which currently may ionly be a keyring file). * Register a resource (which currently may ionly be a keyring file).
*/ */
int int
add_keyblock_resource( const char *filename ) add_keyblock_resource( const char *filename, int force )
{ {
IOBUF iobuf; IOBUF iobuf;
int i; int i;
@ -104,7 +105,7 @@ add_keyblock_resource( const char *filename )
return G10ERR_RESOURCE_LIMIT; return G10ERR_RESOURCE_LIMIT;
iobuf = iobuf_open( filename ); iobuf = iobuf_open( filename );
if( !iobuf ) if( !iobuf && !force )
return G10ERR_OPEN_FILE; return G10ERR_OPEN_FILE;
resource_table[i].used = 1; resource_table[i].used = 1;
resource_table[i].fname = m_strdup(filename); 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 * Lock the keyblock; wait until it's available
@ -182,22 +208,19 @@ lock_keyblock( KBPOS *kbpos )
{ {
int rc; int rc;
if( (rc=check_pos(kbpos)) ) if( !check_pos(kbpos) )
return rc; return G10ERR_GENERAL;
return 0; return 0;
} }
/**************** /****************
* Release a lock on a keyblock * Release a lock on a keyblock
*/ */
int void
unlock_keyblock( KBPOS *kbpos ) unlock_keyblock( KBPOS *kbpos )
{ {
int rc; if( !check_pos(kbpos) )
log_bug(NULL);
if( (rc=check_pos(kbpos)) )
return rc;
return 0;
} }
/**************** /****************
@ -206,10 +229,8 @@ unlock_keyblock( KBPOS *kbpos )
int int
read_keyblock( KBPOS *kbpos, KBNODE *ret_root ) read_keyblock( KBPOS *kbpos, KBNODE *ret_root )
{ {
int rc; if( !check_pos(kbpos) )
return G10ERR_GENERAL;
if( (rc=check_pos(kbpos)) )
return rc;
return keyring_read( kbpos, ret_root ); return keyring_read( kbpos, ret_root );
} }
@ -222,8 +243,8 @@ insert_keyblock( KBPOS *kbpos, KBNODE root )
{ {
int rc; int rc;
if( (rc=check_pos(kbpos)) ) if( !check_pos(kbpos) )
return rc; return G10ERR_GENERAL;
rc = keyring_insert( kbpos, root ); rc = keyring_insert( kbpos, root );
@ -241,8 +262,8 @@ delete_keyblock( KBPOS *kbpos )
{ {
int rc; int rc;
if( (rc=check_pos(kbpos)) ) if( !check_pos(kbpos) )
return rc; return G10ERR_GENERAL;
rc = keyring_delete( kbpos ); rc = keyring_delete( kbpos );
@ -358,13 +379,26 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root )
{ {
PACKET *pkt; PACKET *pkt;
int rc; int rc;
RESTBL *rentry;
KBNODE root = NULL; KBNODE root = NULL;
KBNODE node, n1, n2; KBNODE node, n1, n2;
IOBUF a; IOBUF a;
if( (rc=check_pos(kbpos)) ) if( !(rentry=check_pos(kbpos)) )
return rc; return G10ERR_GENERAL;
a = resource_table[kbpos->resno].iobuf;
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 ); pkt = m_alloc( sizeof *pkt );
init_packet(pkt); init_packet(pkt);
@ -377,7 +411,7 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root )
case PKT_PUBLIC_CERT: case PKT_PUBLIC_CERT:
case PKT_SECRET_CERT: case PKT_SECRET_CERT:
if( root ) if( root )
break; goto ready;
root = new_kbnode( pkt ); root = new_kbnode( pkt );
pkt = m_alloc( sizeof *pkt ); pkt = m_alloc( sizeof *pkt );
init_packet(pkt); init_packet(pkt);
@ -386,8 +420,8 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root )
case PKT_USER_ID: case PKT_USER_ID:
if( !root ) { if( !root ) {
log_error("read_keyblock: orphaned user id\n" ); log_error("read_keyblock: orphaned user id\n" );
rc = G10ERR_INV_KEYRING; /* or wron kbpos */ rc = G10ERR_INV_KEYRING; /* or wrong kbpos */
break; goto ready;
} }
/* append the user id */ /* append the user id */
node = new_kbnode( pkt ); node = new_kbnode( pkt );
@ -434,6 +468,7 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root )
break; break;
} }
} }
ready:
kbpos->last_block = rc == -1; /* flag, that this is the last block */ kbpos->last_block = rc == -1; /* flag, that this is the last block */
if( rc == -1 && root ) if( rc == -1 && root )
rc = 0; rc = 0;
@ -446,14 +481,49 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root )
} }
free_packet( pkt ); free_packet( pkt );
m_free( pkt ); m_free( pkt );
iobuf_close(a);
return rc; return rc;
} }
/****************
* Insert the keyblock described by ROOT into the keyring described
* by KBPOS. This actually appends the data to the keyfile.
*/
static int static int
keyring_insert( KBPOS *kbpos, KBNODE root ) 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 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 * 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) * returns: A mpi with the session key (caller must free)
*/ */
MPI MPI

View File

@ -64,6 +64,7 @@ IOBUF iobuf_alloc(int usage, size_t bufsize);
IOBUF iobuf_temp(void); IOBUF iobuf_temp(void);
IOBUF iobuf_open( const char *fname ); IOBUF iobuf_open( const char *fname );
IOBUF iobuf_create( const char *fname ); IOBUF iobuf_create( const char *fname );
IOBUF iobuf_append( const char *fname );
int iobuf_close( IOBUF iobuf ); int iobuf_close( IOBUF iobuf );
int iobuf_cancel( IOBUF iobuf ); int iobuf_cancel( IOBUF iobuf );

View File

@ -21,6 +21,7 @@
#define G10_TTYIO_H #define G10_TTYIO_H
void tty_printf( const char *fmt, ... ); void tty_printf( const char *fmt, ... );
void tty_print_string( byte *p, size_t n );
char *tty_get( const char *prompt ); char *tty_get( const char *prompt );
char *tty_get_hidden( const char *prompt ); char *tty_get_hidden( const char *prompt );
void tty_kill_prompt(void); void tty_kill_prompt(void);

View File

@ -5,6 +5,10 @@ CFLAGS += -O2
SUFFIXES = .S .s SUFFIXES = .S .s
SUBDIRS = generic i386
EXTRA_DIST = config.links
noinst_LIBRARIES = mpi noinst_LIBRARIES = mpi
noinst_HEADERS = sysdep.h noinst_HEADERS = sysdep.h

View File

@ -42,6 +42,9 @@ INCLUDES = -I$(top_srcdir)/include
SUFFIXES = .S .s SUFFIXES = .S .s
SUBDIRS = generic i386
EXTRA_DIST = config.links
noinst_LIBRARIES = mpi noinst_LIBRARIES = mpi
noinst_HEADERS = sysdep.h noinst_HEADERS = sysdep.h
@ -158,13 +161,45 @@ libmpi.a: $(mpi_OBJECTS) $(mpi_LIBADD)
$(AR) cru libmpi.a $(mpi_OBJECTS) $(mpi_LIBADD) $(AR) cru libmpi.a $(mpi_OBJECTS) $(mpi_LIBADD)
$(RANLIB) libmpi.a $(RANLIB) libmpi.a
ID: $(HEADERS) $(SOURCES) # This directory's subdirectories are mostly independent; you can cd
here=`pwd` && cd $(srcdir) && mkid -f$$here/ID $(SOURCES) $(HEADERS) # into them and run `make' without going through this Makefile.
# To change the values of `make' variables: instead of editing Makefiles,
# (1) if the variable is set in `config.status', edit `config.status'
# (which will cause the Makefiles to be regenerated when you run `make');
# (2) otherwise, pass the desired values on the `make' command line.
@SET_MAKE@
all-recursive install-data-recursive install-exec-recursive \
installdirs-recursive install-recursive uninstall-recursive \
check-recursive installcheck-recursive info-recursive dvi-recursive \
mostlyclean-recursive clean-recursive distclean-recursive \
maintainer-clean-recursive:
for subdir in $(SUBDIRS); do \
target=`echo $@ | sed s/-recursive//`; \
echo making $$target in $$subdir; \
(cd $$subdir && $(MAKE) $$target) \
|| case "$(MFLAGS)" in *k*) fail=yes;; *) exit 1;; esac; \
done && test -z "$$fail"
tags: TAGS tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) tags-recursive:
here=`pwd` && cd $(srcdir) && etags $(ETAGS_ARGS) $(SOURCES) $(HEADERS) -o $$here/TAGS list="$(SUBDIRS)"; for subdir in $$list; do \
(cd $$subdir && $(MAKE) tags); \
done
TAGS: tags-recursive $(HEADERS) $(SOURCES) $(CONFIG_HEADER) \
$(TAGS_DEPENDENCIES)
tags=; \
here=`pwd`; \
for subdir in $(SUBDIRS); do \
test -f $$subdir/TAGS && { \
tags="$$tags -i $$here/$$subdir/TAGS"; \
}; \
done; \
test -z "$(ETAGS_ARGS)$(CONFIG_HEADER)$(SOURCES)$(HEADERS)$$tags" \
|| etags $(ETAGS_ARGS) $$tags $(CONFIG_HEADER) $(SOURCES) $(HEADERS)
mostlyclean-tags: mostlyclean-tags:
@ -183,6 +218,14 @@ distdir: $(DEP_DISTFILES)
|| ln $(srcdir)/$$file $(distdir)/$$file 2> /dev/null \ || ln $(srcdir)/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $(srcdir)/$$file $(distdir)/$$file; \ || cp -p $(srcdir)/$$file $(distdir)/$$file; \
done done
for subdir in $(SUBDIRS); do \
test -d $(distdir)/$$subdir \
|| mkdir $(distdir)/$$subdir \
|| exit 1; \
chmod 777 $(distdir)/$$subdir; \
(cd $$subdir && $(MAKE) distdir=../$(distdir)/$$subdir distdir) \
|| exit 1; \
done
# This fragment is probably only useful for maintainers. It relies on # This fragment is probably only useful for maintainers. It relies on
# GNU make and gcc. It is only included in the generated Makefile.in # GNU make and gcc. It is only included in the generated Makefile.in
@ -210,28 +253,30 @@ $(srcdir)/.deps/%.P: $(srcdir)/%.c
fi fi
# End of maintainer-only section # End of maintainer-only section
info: info: info-recursive
dvi: dvi: dvi-recursive
check: all check: all check-recursive
installcheck: installcheck: installcheck-recursive
install-exec: all-am: $(LIBFILES) $(HEADERS) Makefile
install-data: install-exec: install-exec-recursive
install: install-exec install-data all install-data: install-data-recursive
install: install-recursive
@: @:
uninstall: uninstall: uninstall-recursive
all: $(LIBFILES) $(HEADERS) Makefile all: all-recursive all-am
install-strip: install-strip:
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install
installdirs: installdirs: installdirs-recursive
mostlyclean-generic: mostlyclean-generic:
@ -247,29 +292,42 @@ distclean-generic:
maintainer-clean-generic: maintainer-clean-generic:
test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
mostlyclean: mostlyclean-noinstLIBRARIES mostlyclean-compile \ mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
mostlyclean-tags mostlyclean-generic mostlyclean-tags mostlyclean-generic
clean: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \ clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
mostlyclean mostlyclean-am
distclean: distclean-noinstLIBRARIES distclean-compile distclean-tags \ distclean-am: distclean-noinstLIBRARIES distclean-compile \
distclean-generic clean distclean-tags distclean-generic clean-am
maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
maintainer-clean-compile maintainer-clean-tags \
maintainer-clean-generic distclean-am
mostlyclean: mostlyclean-am mostlyclean-recursive
clean: clean-am clean-recursive
distclean: distclean-am distclean-recursive
rm -f config.status rm -f config.status
maintainer-clean: maintainer-clean-noinstLIBRARIES \ maintainer-clean: maintainer-clean-am maintainer-clean-recursive
maintainer-clean-compile maintainer-clean-tags \
maintainer-clean-generic distclean
@echo "This command is intended for maintainers to use;" @echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild." @echo "it deletes files that may require special tools to rebuild."
.PHONY: default mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ .PHONY: default mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
mostlyclean-compile distclean-compile clean-compile \ mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile tags mostlyclean-tags distclean-tags \ maintainer-clean-compile install-data-recursive \
clean-tags maintainer-clean-tags distdir info dvi check installcheck \ uninstall-data-recursive install-exec-recursive \
install-exec install-data install uninstall all installdirs \ uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \
mostlyclean-generic distclean-generic clean-generic \ all-recursive check-recursive installcheck-recursive info-recursive \
dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \
maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
distclean-tags clean-tags maintainer-clean-tags distdir info dvi check \
installcheck all-am install-exec install-data install uninstall all \
installdirs mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean maintainer-clean-generic clean mostlyclean distclean maintainer-clean
CFLAGS += -O2 CFLAGS += -O2

51
mpi/config.links Normal file
View File

@ -0,0 +1,51 @@
# sourced my ../configure to get the list of files to link
# this should set $mpi_ln_src and mpi_ln_dst.
# Note: this is called from the above directory.
echo '# created by config.links - do not edit' >./mpi/asm-syntax.h
case "${target}" in
i[3456]86*-*-*)
echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h
echo '#include "./i386/syntax.h"' >>./mpi/asm-syntax.h
path="i386"
;;
i[56]86*-*-* | pentium-*-* | pentiumpro-*-*)
echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h
echo '#include "./i586/syntax.h"' >>./mpi/asm-syntax.h
path="i586"
;;
*)
echo '/* No assembler modules configured */' >>./mpi/asm-syntax.h
path=""
;;
esac
# fixme: grep these modules from Makefile.in
mpi_ln_modules="mpih-add1 mpih-mul1 mpih-mul2 mpih-mul3 \
mpih-shift mpih-sub1"
mpi_ln_objects=
mpi_ln_src=
mpi_ln_dst=
# try to get file to link from the assembler subdirectory and
# if this fails get it from the generic subdirectory.
path="$path generic"
for fn in $mpi_ln_modules ; do
mpi_ln_objects="$mpi_ln_objects $fn.o"
for dir in $path ; do
rm -f ./mpi/$fn.[Sc]
if test -f ./mpi/$dir/$fn.S ; then
mpi_ln_src="$mpi_ln_src mpi/$dir/$fn.S"
mpi_ln_dst="$mpi_ln_dst mpi/$fn.S"
break;
elif test -f ./mpi/$dir/$fn.c ; then
mpi_ln_src="$mpi_ln_src mpi/$dir/$fn.c"
mpi_ln_dst="$mpi_ln_dst mpi/$fn.c"
break;
fi
done
done

View File

@ -194,6 +194,7 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
char keyword[100]; char keyword[100];
char *buffer = NULL; char *buffer = NULL;
size_t buflen = 0; size_t buflen = 0;
int inverse=0;
if( !fp ) /* same as arg_parse() in this case */ if( !fp ) /* same as arg_parse() in this case */
return arg_parse( arg, opts ); return arg_parse( arg, opts );
@ -216,6 +217,8 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
break; break;
index = i; index = i;
arg->r_opt = opts[index].short_opt; arg->r_opt = opts[index].short_opt;
if( inverse )
arg->r_opt = -arg->r_opt;
if( !opts[index].short_opt ) if( !opts[index].short_opt )
arg->r_opt = -2; /* unknown option */ arg->r_opt = -2; /* unknown option */
else if( (opts[index].flags & 8) ) /* no optional argument */ else if( (opts[index].flags & 8) ) /* no optional argument */

View File

@ -370,6 +370,36 @@ iobuf_create( const char *fname )
return a; return a;
} }
/****************
* append to a iobuf if the file does not exits; create it.
* cannont be used for stdout.
*/
IOBUF
iobuf_append( const char *fname )
{
IOBUF a;
FILE *fp;
file_filter_ctx_t *fcx;
size_t len;
if( !fname )
return NULL;
else if( !(fp = fopen(fname, "ab")) )
return NULL;
a = iobuf_alloc(2, 8192 );
fcx = m_alloc( sizeof *fcx + strlen(fname) );
fcx->fp = fp;
strcpy(fcx->fname, fname );
a->filter = file_filter;
a->filter_ov = fcx;
file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
if( DBG_IOBUF )
log_debug("iobuf-%d.%d: append '%s'\n", a->no, a->subno, a->desc );
return a;
}
/**************** /****************
* Register an i/o filter. * Register an i/o filter.
*/ */
@ -709,8 +739,25 @@ iobuf_tell( IOBUF a )
int int
iobuf_seek( IOBUF a, ulong newpos ) iobuf_seek( IOBUF a, ulong newpos )
{ {
file_filter_ctx_t *b = NULL;
return -1; for( ; a; a = a->chain ) {
if( !a->chain && a->filter == file_filter ) {
b = a->filter_ov;
break;
}
}
if( !a )
return -1;
if( fseek( b->fp, newpos, SEEK_SET ) ) {
log_error("can't seek to %lu: %s\n", newpos, strerror(errno) );
return -1;
}
/* FIXME: flush all buffers (and remove filters?)*/
return 0;
} }

View File

@ -46,7 +46,7 @@ print_string( FILE *fp, byte *p, size_t n )
else if( !*p ) else if( !*p )
putc('0', fp); putc('0', fp);
else else
printf("x%02x", *p ); fprintf(fp, "x%02x", *p );
} }
else else
putc(*p, fp); putc(*p, fp);

View File

@ -60,6 +60,28 @@ tty_printf( const char *fmt, ... )
} }
/****************
* Print a string, but filter all control characters out.
*/
void
tty_print_string( byte *p, size_t n )
{
for( ; n; n--, p++ )
if( iscntrl( *p ) ) {
putc('\\', stderr);
if( *p == '\n' )
putc('n', stderr);
else if( !*p )
putc('0', stderr);
else
fprintf(stderr, "x%02x", *p );
}
else
putc(*p, stderr);
}
char * char *
tty_get( const char *prompt ) tty_get( const char *prompt )
{ {