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
* add trust stuff
* make ttyio.c work (hide passwords etc..)
* add option file handling.
* use correct ASN values for DEK encoding
* add checking of armor trailers
* add real secure memory
* 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"
* speed up the RIPE-MD-160
* add signal handling
@ -33,3 +29,11 @@
* complete cipher/cast.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 \
smallprime.c
cipher_LIBADD = rsa.o
##cipher_LIBADD = rsa.o

View File

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

View File

@ -22,21 +22,20 @@ fi
CFLAGS="-g"
dnl
AC_CANONICAL_HOST
AC_CANONICAL_SYSTEM
AC_MSG_CHECKING(cached information)
hostcheck="$host"
hostcheck="$target"
AC_CACHE_VAL(ac_cv_mpi_hostcheck, [ ac_cv_mpi_hostcheck="$hostcheck" ])
if test "$ac_cv_mpi_hostcheck" != "$hostcheck"; then
AC_MSG_RESULT(changed)
AC_MSG_WARN(config.cache exists!)
AC_MSG_ERROR(you must do 'make distclean' first to compile for
different host or different parameters.)
different target or different parameters.)
else
AC_MSG_RESULT(ok)
fi
dnl Checks for programs.
AC_PROG_MAKE_SET
@ -71,8 +70,12 @@ AC_CHECK_FUNCS(strerror strtol strtoul)
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_OUTPUT([ Makefile scripts/Makefile util/Makefile mpi/Makefile \
mpi/generic/Makefile mpi/i386/Makefile \
cipher/Makefile \
include/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->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

View File

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

View File

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

View File

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

View File

@ -42,6 +42,9 @@ INCLUDES = -I$(top_srcdir)/include
SUFFIXES = .S .s
SUBDIRS = generic i386
EXTRA_DIST = config.links
noinst_LIBRARIES = mpi
noinst_HEADERS = sysdep.h
@ -158,13 +161,45 @@ libmpi.a: $(mpi_OBJECTS) $(mpi_LIBADD)
$(AR) cru libmpi.a $(mpi_OBJECTS) $(mpi_LIBADD)
$(RANLIB) libmpi.a
ID: $(HEADERS) $(SOURCES)
here=`pwd` && cd $(srcdir) && mkid -f$$here/ID $(SOURCES) $(HEADERS)
# This directory's subdirectories are mostly independent; you can cd
# 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: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES)
here=`pwd` && cd $(srcdir) && etags $(ETAGS_ARGS) $(SOURCES) $(HEADERS) -o $$here/TAGS
tags-recursive:
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:
@ -183,6 +218,14 @@ distdir: $(DEP_DISTFILES)
|| ln $(srcdir)/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $(srcdir)/$$file $(distdir)/$$file; \
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
# GNU make and gcc. It is only included in the generated Makefile.in
@ -210,28 +253,30 @@ $(srcdir)/.deps/%.P: $(srcdir)/%.c
fi
# 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:
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install
installdirs:
installdirs: installdirs-recursive
mostlyclean-generic:
@ -247,29 +292,42 @@ distclean-generic:
maintainer-clean-generic:
test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
mostlyclean: mostlyclean-noinstLIBRARIES mostlyclean-compile \
mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
mostlyclean-tags mostlyclean-generic
clean: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
mostlyclean
clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
mostlyclean-am
distclean: distclean-noinstLIBRARIES distclean-compile distclean-tags \
distclean-generic clean
distclean-am: distclean-noinstLIBRARIES distclean-compile \
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
maintainer-clean: maintainer-clean-noinstLIBRARIES \
maintainer-clean-compile maintainer-clean-tags \
maintainer-clean-generic distclean
maintainer-clean: maintainer-clean-am maintainer-clean-recursive
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
.PHONY: default mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile tags mostlyclean-tags distclean-tags \
clean-tags maintainer-clean-tags distdir info dvi check installcheck \
install-exec install-data install uninstall all installdirs \
mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-compile install-data-recursive \
uninstall-data-recursive install-exec-recursive \
uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \
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
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 *buffer = NULL;
size_t buflen = 0;
int inverse=0;
if( !fp ) /* same as arg_parse() in this case */
return arg_parse( arg, opts );
@ -216,6 +217,8 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
break;
index = i;
arg->r_opt = opts[index].short_opt;
if( inverse )
arg->r_opt = -arg->r_opt;
if( !opts[index].short_opt )
arg->r_opt = -2; /* unknown option */
else if( (opts[index].flags & 8) ) /* no optional argument */

View File

@ -370,6 +370,36 @@ iobuf_create( const char *fname )
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.
*/
@ -709,8 +739,25 @@ iobuf_tell( IOBUF a )
int
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 )
putc('0', fp);
else
printf("x%02x", *p );
fprintf(fp, "x%02x", *p );
}
else
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 *
tty_get( const char *prompt )
{