diff options
author | Werner Koch <wk@gnupg.org> | 1998-02-11 04:25:44 +0100 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 1998-02-11 04:25:44 +0100 |
commit | 4c0c155922b70b62793905490e210e9af4e3b18d (patch) | |
tree | a0d8d84a89cfd4579817a993715e750917961c3e | |
parent | release 0.2.3 (diff) | |
download | gnupg2-4c0c155922b70b62793905490e210e9af4e3b18d.tar.xz gnupg2-4c0c155922b70b62793905490e210e9af4e3b18d.zip |
a couple of changes; but some parts are now broken
46 files changed, 1877 insertions, 431 deletions
@@ -0,0 +1,5 @@ +Tue Feb 10 11:57:23 1998 Werner Koch (wk@frodo) + + * ddd/hhhh: + + diff --git a/Makefile.in b/Makefile.in index 6097936c5..37e30e864 100644 --- a/Makefile.in +++ b/Makefile.in @@ -93,8 +93,8 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/scripts/mkinstalldirs CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = DIST_COMMON = README ABOUT-NLS AUTHORS COPYING ChangeLog INSTALL \ -Makefile.am Makefile.in NEWS TODO acconfig.h acinclude.m4 aclocal.m4 \ -config.h.in configure configure.in stamp-h.in +Makefile.am Makefile.in NEWS THANKS TODO acconfig.h acinclude.m4 \ +aclocal.m4 config.h.in configure configure.in stamp-h.in DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) @@ -1,3 +1,15 @@ +Noteworthy changes in version 0.2.x +----------------------------------- + + * nearly doubled the speed of the ElGamal signature verification. + + * backup copies of keyrings are created. + + * assembler stuff for Pentium; gives about 15% better perfomance. + + +Noteworthy changes in version 0.2.3 +----------------------------------- * Found a bug in the calculation of ELG fingerprints. This is now fixed, but all existing fingerprints and keyids for ELG keys @@ -0,0 +1,26 @@ +G10 has originally been written by Werner Koch. Other people contributed +by reporting problems, suggesting various improvements or submitting actual +code. Here is a list of these people. Help me keeping it complete and +exempt of errors. + + +Anand Kumria wildfire@progsoc.uts.edu.au +Daniel Eisenbud eisenbud@cs.swarthmore.edu +Detlef Lannert lannert@lannert.rz.uni-duesseldorf.de +Ernst Molitor ernst.molitor@uni-bonn.de +Hendrik Buschkamp buschkamp@rheumanet.org +Jens Bachem bachem@rrz.uni-koeln.de +Peter Gutmann pgut001@cs.auckland.ac.nz +Ralph Gillen gillen@theochem.uni-duesseldorf.de +Thomas Roessler roessler@guug.de +Tomas Fasth tomas.fasth@twinspot.net +Walter Koch walterk@ddorf.rhein-ruhr.de +Werner Koch werner.koch@guug.de +Wim Vandeputte bunbun@reptile.rug.ac.be + + +Thanks to the German Unix User Group for providing FTP space and +Martin Hamilton for hosting the mailing list. + +Many thanks to Gerlinde for having so much patience with me while +hacking late in the evening. @@ -15,8 +15,6 @@ * complete cipher/cast.c * complete cipher/dsa.c - * armor has now some problems. - * add g10 stuff to Mutt's pgpinvoke.c * Burn the buffers used by fopen(). @@ -27,7 +25,4 @@ we have a self-signature -> put this stuff into a kind of directory record, as it does not belong to the pubkey record? - * Have no prototype for stpcpy() when using glibc 2; must switch on - the GNU extensions or see how configure can fix it. - @@ -1 +1 @@ -0.2.3 +0.2.3x diff --git a/cipher/Makefile.in b/cipher/Makefile.in index 9e4860f6a..e4ab5edac 100644 --- a/cipher/Makefile.in +++ b/cipher/Makefile.in @@ -130,7 +130,7 @@ AR = ar CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ -DIST_COMMON = Makefile.am Makefile.in +DIST_COMMON = ChangeLog Makefile.am Makefile.in DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) diff --git a/cipher/blowfish.c b/cipher/blowfish.c index 81e33d080..8e3a49301 100644 --- a/cipher/blowfish.c +++ b/cipher/blowfish.c @@ -228,7 +228,7 @@ static const u32 ps[BLOWFISH_ROUNDS+2] = { -static u32 +static inline u32 function_F( BLOWFISH_context *bc, u32 x ) { u16 a, b, c, d; diff --git a/cipher/elgamal.c b/cipher/elgamal.c index 5e6bd0c84..13b8579fe 100644 --- a/cipher/elgamal.c +++ b/cipher/elgamal.c @@ -311,25 +311,37 @@ elg_verify(MPI a, MPI b, MPI input, ELG_public_key *pkey ) int rc; MPI t1; MPI t2; + MPI base[4]; + MPI exp[4]; if( !(mpi_cmp_ui( a, 0 ) > 0 && mpi_cmp( a, pkey->p ) < 0) ) return 0; /* assertion 0 < a < p failed */ t1 = mpi_alloc( mpi_get_nlimbs(a) ); t2 = mpi_alloc( mpi_get_nlimbs(a) ); - /* t1 = (y^a mod p) * (a^b mod p) mod p - * fixme: should be calculated by a call which evalutes - * t1 = y^a * a^b mod p - * direct. - */ - mpi_powm( t1, pkey->y, a, pkey->p ); - mpi_powm( t2, a, b, pkey->p ); - mpi_mulm( t1, t1, t2, pkey->p ); + + #if 0 + /* t1 = (y^a mod p) * (a^b mod p) mod p */ + base[0] = pkey->y; exp[0] = a; + base[1] = a; exp[1] = b; + base[2] = NULL; exp[2] = NULL; + mpi_mulpowm( t1, base, exp, pkey->p ); /* t2 = g ^ input mod p */ mpi_powm( t2, pkey->g, input, pkey->p ); rc = !mpi_cmp( t1, t2 ); + #else + /* t1 = g ^ - input * y ^ a * a ^ b mod p */ + mpi_invm(t2, pkey->g, pkey->p ); + base[0] = t2 ; exp[0] = input; + base[1] = pkey->y; exp[1] = a; + base[2] = a; exp[2] = b; + base[3] = NULL; exp[3] = NULL; + mpi_mulpowm( t1, base, exp, pkey->p ); + rc = !mpi_cmp_ui( t1, 1 ); + + #endif mpi_free(t1); mpi_free(t2); diff --git a/cipher/md5.c b/cipher/md5.c index c9f9a86b4..ef95c7ef8 100644 --- a/cipher/md5.c +++ b/cipher/md5.c @@ -93,7 +93,18 @@ static byte PADDING[64] = { #define I(x, y, z) ((y) ^ ((x) | (~z))) /* ROTATE_LEFT rotates x left n bits */ -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) +#if defined(__GNUC__) && defined(__i386__) +static inline u32 +ROTATE_LEFT(u32 x, int n) +{ + __asm__("roll %%cl,%0" + :"=r" (x) + :"0" (x),"c" (n)); + return x; +} +#else + #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) +#endif /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ /* Rotation is separate from addition to prevent recomputation */ diff --git a/cipher/rmd160.c b/cipher/rmd160.c index 0b501d77b..39f1c740c 100644 --- a/cipher/rmd160.c +++ b/cipher/rmd160.c @@ -151,6 +151,20 @@ rmd160_init( RMD160_CONTEXT *hd ) } +#if defined(__GNUC__) && defined(__i386__) +static inline u32 +rol(int n, u32 x) +{ + __asm__("roll %%cl,%0" + :"=r" (x) + :"0" (x),"c" (n)); + return x; +} +#else + #define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) ) +#endif + + /**************** * Transform the message X which consists of 16 32-bit-words */ @@ -209,9 +223,6 @@ transform( RMD160_CONTEXT *hd, byte *data ) (a) < 64 ? F3((x),(y),(z)) : \ F4((x),(y),(z)) ) -#define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) ) - - #ifdef BIG_ENDIAN_HOST { int i; byte *p2, *p1; diff --git a/cipher/sha1.c b/cipher/sha1.c index 51029c451..a54ec6a80 100644 --- a/cipher/sha1.c +++ b/cipher/sha1.c @@ -99,14 +99,30 @@ #define K3 0x8F1BBCDCL /* Rounds 40-59 */ #define K4 0xCA62C1D6L /* Rounds 60-79 */ -#define ROTL(n,X) ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) ) + +#if defined(__GNUC__) && defined(__i386__) +static inline u32 +rol(int n, u32 x) +{ + __asm__("roll %%cl,%0" + :"=r" (x) + :"0" (x),"c" (n)); + return x; +} +#else + #define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) ) +#endif + + + + #define expand(W,i) ( W[ i & 15 ] = \ - ROTL( 1, ( W[ i & 15 ] ^ W[ (i - 14) & 15 ] ^ \ + rol( 1, ( W[ i & 15 ] ^ W[ (i - 14) & 15 ] ^ \ W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] ) ) ) #define subRound(a, b, c, d, e, f, k, data) \ - ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) ) + ( e += rol( 5, a ) + f( b, c, d ) + k + data, b = rol( 30, b ) ) void diff --git a/g10/Makefile.in b/g10/Makefile.in index 6bcb29e40..bae7c65a9 100644 --- a/g10/Makefile.in +++ b/g10/Makefile.in @@ -174,7 +174,7 @@ g10maint_LDFLAGS = CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ -DIST_COMMON = Makefile.am Makefile.in +DIST_COMMON = ChangeLog Makefile.am Makefile.in DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) @@ -291,7 +291,7 @@ main( int argc, char **argv ) configname, strerror(errno) ); m_free(configname); configname = NULL; } - if( parse_verbose > 1 ) + if( parse_verbose > 1 && configname ) log_info(_("reading options from '%s'\n"), configname ); default_config = 0; } @@ -640,7 +640,7 @@ main( int argc, char **argv ) void g10_exit( int rc ) { - if( opt.verbose ) + if( opt.debug ) secmem_dump_stats(); secmem_term(); rc = rc? rc : log_get_errorcount(0)? 2:0; diff --git a/g10/g10maint.c b/g10/g10maint.c index 4352045c1..e8a44372c 100644 --- a/g10/g10maint.c +++ b/g10/g10maint.c @@ -478,7 +478,7 @@ main( int argc, char **argv ) } break; - case aTest: do_test( argc? atoi(*argv): 0 ); break; + case aTest: do_test( argc? atoi(*argv): 1 ); break; case aListTrustDB: if( !argc ) @@ -603,27 +603,41 @@ print_mds( const char *fname ) static void do_test(int times) { - #if 0 - MPI t = mpi_alloc( 50 ); - MPI m = mpi_alloc( 50 ); - MPI a = mpi_alloc( 50 ); - MPI b = mpi_alloc( 50 ); - MPI p = mpi_alloc( 50 ); - MPI x = mpi_alloc( 50 ); - - /* output = b/(a^x) mod p */ - log_debug("invm %d times ", times); - for( ; times > 0; times -- ) { - mpi_fromstr(a, "0xef45678343589854354a4545545454554545455" - "aaaaaaaaaaaaa44444fffdecb33434343443331" ); - mpi_fromstr(b, "0x8765765589854354a4545545454554545455" - "aaaaaaa466577778decb36666343443331" ); - mpi_invm( t, a, b ); - fputc('.', stderr); fflush(stderr); - } + MPI base[4]; + MPI exp[4]; + MPI t1 = mpi_alloc(50); + MPI t2 = mpi_alloc(50); + MPI t3 = mpi_alloc(50); + MPI tmp= mpi_alloc(50); + MPI m = mpi_alloc(50); + MPI res = mpi_alloc(50); + + mpi_fromstr( m, "0x10000000000000000000000000" ); + base[0] = mpi_alloc_set_ui( 3 ); + mpi_fromstr( base[0], "0x145984358945989898495ffdd13" ); + base[1] = mpi_alloc_set_ui( 5 ); + mpi_fromstr( base[1], "0x000effff9999000000001100001" ); + base[2] = mpi_alloc_set_ui( 2 ); + mpi_fromstr( base[2], "0x499eeeaaaaa0444444545466672" ); + base[3] = NULL; + exp[0] = mpi_alloc_set_ui( 30 ); + exp[1] = mpi_alloc_set_ui( 10 ); + mpi_fromstr( exp[1], "0x3457878888888888aabbbccccc1" ); + exp[2] = mpi_alloc_set_ui( 24 ); + exp[3] = NULL; + + mpi_powm( t1, base[0], exp[0], m ); + mpi_powm( t2, base[1], exp[1], m ); + mpi_powm( t3, base[2], exp[2], m ); + mpi_mulm( tmp, t1, t2, m ); + mpi_mulm( t1, tmp, t3, m ); + log_mpidump("X=", t1 ); + + + mpi_mulpowm( res, base, exp, m ); + log_mpidump("X=", res ); m_check(NULL); - #endif } diff --git a/g10/kbnode.c b/g10/kbnode.c index 19e0870df..3096c4df5 100644 --- a/g10/kbnode.c +++ b/g10/kbnode.c @@ -36,7 +36,6 @@ new_kbnode( PACKET *pkt ) KBNODE n = m_alloc( sizeof *n ); n->next = NULL; n->pkt = pkt; - n->child = NULL; n->flag = 0; n->private_flag=0; /* kludge to delete a node */ return n; @@ -50,7 +49,6 @@ release_kbnode( KBNODE n ) while( n ) { n2 = n->next; - release_kbnode( n->child ); free_packet( n->pkt ); m_free( n ); n = n2; @@ -60,7 +58,7 @@ release_kbnode( KBNODE n ) /**************** * Delete NODE from ROOT, ROOT must exist! - * Note does only work with walk_kbtree!! + * Note: This does only work with walk_kbnode!! */ void delete_kbnode( KBNODE root, KBNODE node ) @@ -82,56 +80,97 @@ add_kbnode( KBNODE root, KBNODE node ) } /**************** - * Append NODE to ROOT as child of ROOT + * Insert NODE into the list after root but before a packet with type PKTTYPE + * (only if PKTTYPE != 0) */ void -add_kbnode_as_child( KBNODE root, KBNODE node ) +insert_kbnode( KBNODE root, KBNODE node, int pkttype ) { - KBNODE n1; - - if( !(n1=root->child) ) - root->child = node; + if( !pkttype ) { + node->next = root->next; + root->next = node; + } else { - for( ; n1->next; n1 = n1->next) - ; + KBNODE n1; + + for(n1=root; n1->next; n1 = n1->next) + if( pkttype == n1->next->pkt->pkttype ) { + node->next = n1->next; + n1->next = node; + return; + } + /* no such packet, append */ + node->next = NULL; n1->next = node; } } + /**************** - * Return the parent node of KBNODE from the tree with ROOT + * Find the previous node (if PKTTYPE = 0) or the previous node + * with pkttype PKTTYPE in the list starting with ROOT of NODE. */ KBNODE -find_kbparent( KBNODE root, KBNODE node ) +find_prev_kbnode( KBNODE root, KBNODE node, int pkttype ) { - KBNODE n, n2; + KBNODE n1; - for( ; root; root = root->child) { - for( n = root; n; n = n->next) { - for( n2 = n->child; n2; n2 = n2->next ) { - if( n2 == node ) - return n; - } - } + for(n1=NULL ; root && root != node; root = root->next ) + if( !pkttype || root->pkt->pkttype == pkttype ) + n1 = root; + return n1; +} + +/**************** + * Ditto, but find the next package. The behaviour is trivial if + * PKTTYPE is 0 but if it is specified, the next node with a packet + * of this type is returned. The function has some knowledge about + * the valid ordering of packets: e.g. if the next signature packet + * is requested, the function will not return one if it encounters + * a user-id. + */ +KBNODE +find_next_kbnode( KBNODE node, int pkttype ) +{ + for( node=node->next ; node; node = node->next ) { + if( !pkttype ) + return node; + else if( pkttype == PKT_USER_ID + && ( node->pkt->pkttype == PKT_PUBLIC_CERT + || node->pkt->pkttype == PKT_SECRET_CERT ) ) + return NULL; + else if( pkttype == PKT_SIGNATURE + && ( node->pkt->pkttype == PKT_USER_ID + || node->pkt->pkttype == PKT_PUBLIC_CERT + || node->pkt->pkttype == PKT_SECRET_CERT ) ) + return NULL; + else if( node->pkt->pkttype == pkttype ) + return node; + } + return NULL; +} + + +KBNODE +find_kbnode( KBNODE node, int pkttype ) +{ + for( ; node; node = node->next ) { + if( node->pkt->pkttype == pkttype ) + return node; } return NULL; } + /**************** - * Walk through a tree of kbnodes. This functions returns + * Walk through a list 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 ) -{ - return walk_kbtree2( root, context, 0 ); -} - -KBNODE -walk_kbtree2( KBNODE root, KBNODE *context, int all ) +walk_kbnode( KBNODE root, KBNODE *context, int all ) { KBNODE n; @@ -142,15 +181,7 @@ walk_kbtree2( KBNODE root, KBNODE *context, int all ) } 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 )) ) { + if( n->next ) { n = n->next; *context = n; } @@ -163,7 +194,6 @@ void clear_kbnode_flags( KBNODE n ) { for( ; n; n = n->next ) { - clear_kbnode_flags( n->child ); n->flag = 0; } } diff --git a/g10/keydb.h b/g10/keydb.h index 818b64307..ff0ecb528 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -37,9 +37,8 @@ typedef struct kbnode_struct *KBNODE; struct kbnode_struct { + KBNODE next; PACKET *pkt; - KBNODE next; /* used to form a link list */ - KBNODE child; int flag; int private_flag; }; @@ -49,10 +48,9 @@ struct kbnode_struct { * of a keyblock. */ struct keyblock_pos_struct { - int resno; /* resource number */ - ulong offset; /* position information */ - ulong length; /* length of thge keyblock */ - int last_block; + int resno; /* resource number */ + ulong offset; /* position information */ + unsigned count; /* length of the keyblock in packets */ }; typedef struct keyblock_pos_struct KBPOS; @@ -130,10 +128,11 @@ KBNODE new_kbnode( PACKET *pkt ); void release_kbnode( KBNODE n ); void delete_kbnode( KBNODE root, KBNODE node ); 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 ); -KBNODE walk_kbtree2( KBNODE root, KBNODE *context, int all ); +void insert_kbnode( KBNODE root, KBNODE node, int pkttype ); +KBNODE find_prev_kbnode( KBNODE root, KBNODE node, int pkttype ); +KBNODE find_next_kbnode( KBNODE node, int pkttype ); +KBNODE find_kbnode( KBNODE node, int pkttype ); +KBNODE walk_kbnode( KBNODE root, KBNODE *context, int all ); void clear_kbnode_flags( KBNODE n ); /*-- ringedit.c --*/ diff --git a/g10/keygen.c b/g10/keygen.c index d73573cb1..09d2dc222 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -102,25 +102,19 @@ write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_cert *skc ) PKT_signature *sig; PKT_user_id *uid; int rc=0; - KBNODE kbctx, node; + KBNODE 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; - } + /* get the uid packet from the list */ + node = find_kbnode( root, PKT_USER_ID ); if( !node ) BUG(); /* 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; - } + node = find_kbnode( root, PKT_PUBLIC_CERT ); if( !node ) BUG(); pkc = node->pkt->pkt.public_cert; diff --git a/g10/mainproc.c b/g10/mainproc.c index cae7ddda8..1ef8a8b96 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -110,13 +110,13 @@ add_secret_cert( CTX c, PACKET *pkt ) static int add_user_id( CTX c, PACKET *pkt ) { - KBNODE node, n1, n2; + KBNODE node, n1; if( !c->cert ) { log_error("orphaned user id\n" ); return 0; } - /* goto the last certificate (currently ther is only one) */ + /* goto the last certificate */ for(n1=c->cert; n1->next; n1 = n1->next ) ; assert( n1->pkt ); @@ -127,13 +127,7 @@ add_user_id( CTX c, PACKET *pkt ) } /* add a new user id node at the end */ node = new_kbnode( pkt ); - if( !(n2=n1->child) ) - n1->child = node; - else { - for( ; n2->next; n2 = n2->next) - ; - n2->next = node; - } + add_kbnode( n1, node ); return 1; } @@ -147,49 +141,36 @@ add_signature( CTX c, PACKET *pkt ) /* This is the first signature for a following datafile. * G10 does not write such packets, instead it always uses * onepass-sig packets. The drawback of PGP's method - * of writing prepending the signtaure to the data is, - * that it is not possible to make a signature from data - * read from stdin. But we are able to read these stuff. */ + * of prepending the signtaure to the data is, + * that it is not possible to make a signature from data read + * from stdin. (Anyway, G10 is are able to read these stuff) */ node = new_kbnode( pkt ); - node->next = c->cert; c->cert = node; return 1; } else if( !c->cert ) - return 0; + return 0; /* oops */ else if( !c->cert->pkt ) BUG(); else if( c->cert->pkt->pkttype == PKT_ONEPASS_SIG ) { - /* The root is a onepass signature, so we are signing data - * The childs direct under the root are the signatures - * (there is no need to keep the correct sequence of packets) */ + /* The root is a onepass signature, so we are signing data */ node = new_kbnode( pkt ); - node->next = c->cert->child; - c->cert->child = node; + add_kbnode( c->cert, node ); return 1; } - else if( !c->cert->child ) { - log_error("orphaned signature (no userid)\n" ); - return 0; - } /* goto the last user id */ - for(n1=c->cert->child; n1->next; n1 = n1->next ) - ; - assert( n1->pkt ); - if( n1->pkt->pkttype != PKT_USER_ID ) { - log_error("invalid parent type %d for sig\n", n1->pkt->pkttype); + for(n2=NULL, n1=c->cert; n1->next; n1 = n1->next ) + if( n1->pkt->pkttype == PKT_USER_ID ) + n2 = n1; + if( !n2 ) { + log_error("no user id for signature packet\n"); return 0; } + n1 = n2; /* and add a new signature node id at the end */ node = new_kbnode( pkt ); - if( !(n2=n1->child) ) - n1->child = node; - else { - for( ; n2->next; n2 = n2->next) - ; - n2->next = node; - } + insert_kbnode( n1, node, PKT_USER_ID ); return 1; } @@ -333,10 +314,9 @@ do_check_sig( CTX c, KBNODE node ) } else if( (sig->sig_class&~3) == 0x10 ) { /* classes 0x10 .. 0x13 */ if( c->cert->pkt->pkttype == PKT_PUBLIC_CERT ) { - KBNODE n1 = find_kbparent( c->cert, node ); - - if( n1 && n1->pkt->pkttype == PKT_USER_ID ) { + KBNODE n1 = find_prev_kbnode( c->cert, node, PKT_USER_ID ); + if( n1 ) { if( c->cert->pkt->pkt.public_cert->mfx.md ) md = md_copy( c->cert->pkt->pkt.public_cert->mfx.md ); else @@ -411,7 +391,7 @@ print_fingerprint( PKT_public_cert *pkc, PKT_secret_cert *skc ) static void list_node( CTX c, KBNODE node ) { - register KBNODE n2; + int any=0; if( !node ) ; @@ -422,21 +402,19 @@ list_node( CTX c, KBNODE node ) pubkey_letter( pkc->pubkey_algo ), (ulong)keyid_from_pkc( pkc, NULL ), datestr_from_pkc( pkc ) ); - n2 = node->child; - if( !n2 ) - printf("ERROR: no user id!\n"); - else { - /* and now list all userids with their signatures */ - for( ; n2; n2 = n2->next ) { - if( n2 != node->child ) - printf( "%*s", 31, "" ); - print_userid( n2->pkt ); - putchar('\n'); - if( opt.fingerprint && n2 == node->child ) - print_fingerprint( pkc, NULL ); - list_node(c, n2 ); - } + /* and now list all userids with their signatures */ + while( (node = find_next_kbnode(node, PKT_USER_ID)) ) { + if( any ) + printf( "%*s", 31, "" ); + print_userid( node->pkt ); + putchar('\n'); + if( opt.fingerprint && !any ) + print_fingerprint( pkc, NULL ); + list_node(c, node ); + any=1; } + if( !any ) + printf("ERROR: no user id!\n"); } else if( node->pkt->pkttype == PKT_SECRET_CERT ) { PKT_secret_cert *skc = node->pkt->pkt.secret_cert; @@ -445,20 +423,21 @@ list_node( CTX c, KBNODE node ) pubkey_letter( skc->pubkey_algo ), (ulong)keyid_from_skc( skc, NULL ), datestr_from_skc( skc ) ); - n2 = node->child; - if( !n2 ) - printf("ERROR: no user id!\n"); - else { - print_userid( n2->pkt ); + /* and now list all userids */ + while( (node = find_next_kbnode(node, PKT_USER_ID)) ) { + print_userid( node->pkt ); putchar('\n'); - if( opt.fingerprint && n2 == node->child ) + if( opt.fingerprint && !any ) print_fingerprint( NULL, skc ); + any=1; } + if( !any ) + printf("ERROR: no user id!\n"); } else if( node->pkt->pkttype == PKT_USER_ID ) { /* list everything under this user id */ - for(n2=node->child; n2; n2 = n2->next ) - list_node(c, n2 ); + while( (node = find_next_kbnode(node, 0 )) ) + list_node(c, node ); } else if( node->pkt->pkttype == PKT_SIGNATURE ) { PKT_signature *sig = node->pkt->pkt.signature; @@ -467,7 +446,6 @@ list_node( CTX c, KBNODE node ) char *p; int sigrc = ' '; - assert( !node->child ); if( !opt.list_sigs ) return; @@ -626,31 +604,26 @@ proc_tree( CTX c, KBNODE node ) else if( node->pkt->pkttype == PKT_SECRET_CERT ) list_node( c, node ); else if( node->pkt->pkttype == PKT_ONEPASS_SIG ) { - if( !node->child ) - log_error("proc_tree: onepass_sig without data\n"); - else if( node->child->pkt->pkttype != PKT_SIGNATURE ) - log_error("proc_tree: onepass_sig not followed by signature\n"); - else { /* check all signatures */ - if( !c->have_data ) { - free_md_filter_context( &c->mfx ); - /* prepare to create all requested message digests */ - c->mfx.md = md_open(0, 0); - for(n1=node->child; n1; n1 = n1->next ) { - md_enable( c->mfx.md, - digest_algo_from_sig(n1->pkt->pkt.signature)); - } - /* ask for file and hash it */ - rc = ask_for_detached_datafile( &c->mfx, - iobuf_get_fname(c->iobuf)); - if( rc ) { - log_error("can't hash datafile: %s\n", g10_errstr(rc)); - return; - } + /* check all signatures */ + if( !c->have_data ) { + free_md_filter_context( &c->mfx ); + /* prepare to create all requested message digests */ + c->mfx.md = md_open(0, 0); + for( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); ) { + md_enable( c->mfx.md, + digest_algo_from_sig(n1->pkt->pkt.signature)); + } + /* ask for file and hash it */ + rc = ask_for_detached_datafile( &c->mfx, + iobuf_get_fname(c->iobuf)); + if( rc ) { + log_error("can't hash datafile: %s\n", g10_errstr(rc)); + return; } - - for(n1=node->child; n1; n1 = n1->next ) - check_sig_and_print( c, n1 ); } + + for( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); ) + check_sig_and_print( c, n1 ); } else if( node->pkt->pkttype == PKT_SIGNATURE ) { PKT_signature *sig = node->pkt->pkt.signature; diff --git a/g10/packet.h b/g10/packet.h index 8d3018d58..d0bb3c499 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -221,6 +221,9 @@ int list_packets( IOBUF a ); int set_packet_list_mode( int mode ); int search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos ); int parse_packet( IOBUF inp, PACKET *ret_pkt); +int copy_all_packets( IOBUF inp, IOBUF out ); +int copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff ); +int skip_some_packets( IOBUF inp, unsigned n ); /*-- build-packet.c --*/ int build_packet( IOBUF inp, PACKET *pkt ); diff --git a/g10/parse-packet.c b/g10/parse-packet.c index c49b6f513..2e3cf21be 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -37,7 +37,9 @@ static mpi_print_mode = 0; static list_mode = 0; static int parse( IOBUF inp, PACKET *pkt, int reqtype, - ulong *retpos, int *skip ); + ulong *retpos, int *skip, IOBUF out, int do_skip ); +static int copy_packet( IOBUF inp, IOBUF out, int pkttype, + unsigned long pktlen ); static void skip_packet( IOBUF inp, int pkttype, unsigned long pktlen ); static void skip_rest( IOBUF inp, unsigned long pktlen ); static int parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, @@ -51,7 +53,8 @@ static int parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen, static int parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ); static void parse_subkey( IOBUF inp, int pkttype, unsigned long pktlen ); -static void parse_comment( IOBUF inp, int pkttype, unsigned long pktlen ); +static int parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet ); static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen ); static int parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt ); @@ -116,13 +119,13 @@ parse_packet( IOBUF inp, PACKET *pkt ) int skip, rc; do { - rc = parse( inp, pkt, 0, NULL, &skip ); + rc = parse( inp, pkt, 0, NULL, &skip, NULL, 0 ); } while( skip ); return rc; } /**************** - * Like parse packet, but do only return packet of the given type. + * Like parse packet, but do only return packets of the given type. */ int search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos ) @@ -130,20 +133,68 @@ search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos ) int skip, rc; do { - rc = parse( inp, pkt, pkttype, retpos, &skip ); + rc = parse( inp, pkt, pkttype, retpos, &skip, NULL, 0 ); } while( skip ); return rc; } +/**************** + * Copy all packets from INP to OUT, thereby removing unused spaces. + */ +int +copy_all_packets( IOBUF inp, IOBUF out ) +{ + PACKET pkt; + int skip, rc=0; + do { + init_packet(&pkt); + } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 ))); + return rc; +} + +/**************** + * Copy some packets from INP to OUT, thereby removing unused spaces. + * Stop after at offset STOPoff (i.e. don't copy the packet at this offset) + */ +int +copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff ) +{ + PACKET pkt; + int skip, rc=0; + do { + if( iobuf_tell(inp) >= stopoff ) + return 0; + init_packet(&pkt); + } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 )) ); + return rc; +} + +/**************** + * Skip over N packets + */ +int +skip_some_packets( IOBUF inp, unsigned n ) +{ + int skip, rc=0; + PACKET pkt; + + for( ;n && !rc; n--) { + init_packet(&pkt); + rc = parse( inp, &pkt, 0, NULL, &skip, NULL, 1 ); + } + return rc; +} /**************** * Parse packet. Set the variable skip points to to 1 if the packet * should be skipped; this is the case if either there is a * requested packet type and the parsed packet doesn't match or the * packet-type is 0, indicating deleted stuff. + * if OUT is not NULL, a special copymode is used. */ static int -parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos, int *skip ) +parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos, + int *skip, IOBUF out, int do_skip ) { int rc, c, ctb, pkttype, lenbytes; unsigned long pktlen; @@ -206,7 +257,15 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos, int *skip ) } } - if( !pkttype || (reqtype && pkttype != reqtype) ) { + if( out && pkttype ) { + if( iobuf_write( out, hdr, hdrlen ) == -1 ) + rc = G10ERR_WRITE_FILE; + else + rc = copy_packet(inp, out, pkttype, pktlen ); + return rc; + } + + if( do_skip || !pkttype || (reqtype && pkttype != reqtype) ) { skip_packet(inp, pkttype, pktlen); *skip = 1; return 0; @@ -245,7 +304,7 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos, int *skip ) parse_subkey(inp, pkttype, pktlen); break; case PKT_COMMENT: - parse_comment(inp, pkttype, pktlen); + rc = parse_comment(inp, pkttype, pktlen, pkt); break; case PKT_RING_TRUST: parse_trust(inp, pkttype, pktlen); @@ -284,6 +343,37 @@ dump_hex_line( int c, int *i ) } +static int +copy_packet( IOBUF inp, IOBUF out, int pkttype, unsigned long pktlen ) +{ + int n; + char buf[100]; + + if( iobuf_in_block_mode(inp) ) { + while( (n = iobuf_read( inp, buf, 100 )) != -1 ) + if( iobuf_write(out, buf, n ) ) + return G10ERR_WRITE_FILE; /* write error */ + } + else if( !pktlen && pkttype == PKT_COMPRESSED ) { + /* compressed packet, copy till EOF */ + while( (n = iobuf_read( inp, buf, 100 )) != -1 ) + if( iobuf_write(out, buf, n ) ) + return G10ERR_WRITE_FILE; /* write error */ + } + else { + for( ; pktlen; pktlen -= n ) { + n = pktlen > 100 ? 100 : pktlen; + n = iobuf_read( inp, buf, n ); + if( n == -1 ) + return G10ERR_READ_FILE; + if( iobuf_write(out, buf, n ) ) + return G10ERR_WRITE_FILE; /* write error */ + } + } + return 0; +} + + static void skip_packet( IOBUF inp, int pkttype, unsigned long pktlen ) { @@ -738,22 +828,29 @@ parse_subkey( IOBUF inp, int pkttype, unsigned long pktlen ) -static void -parse_comment( IOBUF inp, int pkttype, unsigned long pktlen ) +static int +parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) { + byte *p; + + packet->pkt.comment = m_alloc(sizeof *packet->pkt.comment + pktlen - 1); + packet->pkt.comment->len = pktlen; + p = packet->pkt.comment->data; + for( ; pktlen; pktlen--, p++ ) + *p = iobuf_get_noeof(inp); + if( list_mode ) { - printf(":comment packet: \"" ); - for( ; pktlen; pktlen-- ) { - int c; - c = iobuf_get_noeof(inp); - if( c >= ' ' && c <= 'z' ) - putchar(c); + int n = packet->pkt.comment->len; + printf(":comment packet: \""); + for(p=packet->pkt.comment->data; n; p++, n-- ) { + if( *p >= ' ' && *p <= 'z' ) + putchar(*p); else - printf("\\x%02x", c ); + printf("\\x%02x", *p ); } printf("\"\n"); } - skip_rest(inp, pktlen); + return 0; } @@ -765,33 +862,6 @@ parse_trust( IOBUF inp, int pkttype, unsigned long pktlen ) c = iobuf_get_noeof(inp); if( list_mode ) printf(":trust packet: flag=%02x\n", c ); - #if 0 /* fixme: depending on the context we have different interpretations*/ - if( prev_packet_is_a_key_packet ) { - int ot = c & 7; /* ownertrust bits (for the key owner) */ - - !ot ? "undefined" : - ot == 1 ? "unknown" : /* we don't know the owner of this key */ - ot == 2 ? "no" : /* usually we do not trust this key owner */ - /* to sign other keys */ - ot == 5 ? "usually" : /* usually we trust this key owner to sign */ - ot == 6 ? "always" : /* always trust this key owner to sign */ - ot == 7 ? "ultimate" : /* also present in the secret keyring */ - "" /* reserved value */ - if( c & (1<<5) ) - "key is disabled" - if( c & (1<<7) ) - "buckstop" - else if( prev_packet_is_user_is_packet ) { - int kl = c & 3; /* keylegit bits */ - 0 = "unknown, undefined, or uninitialized trust" - 1 = "we do not trust this key's ownership" - 2 = "we have marginal confidence of this key's ownership" - 3 = "we completely trust this key's ownership." - if( c & 0x80 ) - "warnonly" - else if( prev_packet_is_a_signature ) { - } - #endif } diff --git a/g10/ringedit.c b/g10/ringedit.c index 61f915c17..141d8cf7f 100644 --- a/g10/ringedit.c +++ b/g10/ringedit.c @@ -35,7 +35,6 @@ * * - Delete a key block * - * FIXME: Add backup stuff * FIXME: Keep track of all nodes, so that a change is propagated * to all nodes. (or use shallow copies and ref-counting?) */ @@ -46,6 +45,9 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> #include <assert.h> #include "util.h" #include "packet.h" @@ -75,8 +77,7 @@ static int keyring_search( PACKET *pkt, KBPOS *kbpos, IOBUF iobuf ); static int keyring_search2( PUBKEY_FIND_INFO info, KBPOS *kbpos, const char *fname); static int keyring_read( KBPOS *kbpos, KBNODE *ret_root ); -static int keyring_insert( KBPOS *kbpos, KBNODE root ); -static int keyring_delete( KBPOS *kbpos ); +static int keyring_copy( KBPOS *kbpos, int mode, KBNODE root ); @@ -308,7 +309,7 @@ insert_keyblock( KBPOS *kbpos, KBNODE root ) if( !check_pos(kbpos) ) return G10ERR_GENERAL; - rc = keyring_insert( kbpos, root ); + rc = keyring_copy( kbpos, 1, root ); return rc; } @@ -327,7 +328,7 @@ delete_keyblock( KBPOS *kbpos ) if( !check_pos(kbpos) ) return G10ERR_GENERAL; - rc = keyring_delete( kbpos ); + rc = keyring_copy( kbpos, 2, NULL ); return rc; } @@ -340,14 +341,11 @@ int update_keyblock( KBPOS *kbpos, KBNODE root ) { int rc; - KBPOS kbpos2; - /* we do it the simple way: */ - memset( &kbpos2, 0, sizeof kbpos2 ); - kbpos2.resno = kbpos->resno; - rc = insert_keyblock( &kbpos2, root ); - if( !rc ) - rc = delete_keyblock( kbpos ); + if( !check_pos(kbpos) ) + return G10ERR_GENERAL; + + rc = keyring_copy( kbpos, 3, root ); return rc; } @@ -451,20 +449,12 @@ keyring_search2( PUBKEY_FIND_INFO info, KBPOS *kbpos, const char *fname ) init_packet(&pkt); save_mode = set_packet_list_mode(0); - #if 0 - if( iobuf_seek( iobuf, 0 ) ) { - log_error("can't rewind keyring file: %s\n", g10_errstr(rc)); - rc = G10ERR_KEYRING_OPEN; - goto leave; - } - #else iobuf = iobuf_open( fname ); if( !iobuf ) { log_error("can't open '%s'\n", fname ); rc = G10ERR_OPEN_FILE; goto leave; } - #endif while( !(rc=search_packet(iobuf, &pkt, PKT_PUBLIC_CERT, &offset)) ) { PKT_public_cert *pkc = pkt.pkt.public_cert; @@ -505,9 +495,8 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root ) int rc; RESTBL *rentry; KBNODE root = NULL; - KBNODE node, n1, n2; IOBUF a; - u32 offset, last_offset; + int in_cert = 0; if( !(rentry=check_pos(kbpos)) ) return G10ERR_GENERAL; @@ -526,77 +515,37 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root ) pkt = m_alloc( sizeof *pkt ); init_packet(pkt); + kbpos->count=0; while( (rc=parse_packet(a, pkt)) != -1 ) { if( rc ) { /* ignore errors */ + if( rc != G10ERR_UNKNOWN_PACKET ) { + log_error("read_keyblock: read error: %s\n", g10_errstr(rc) ); + rc = G10ERR_INV_KEYRING; + goto ready; + } + kbpos->count++; free_packet( pkt ); continue; } - if( root && ( pkt->pkttype == PKT_PUBLIC_CERT - || pkt->pkttype == PKT_SECRET_CERT ) ) - goto ready; - offset = iobuf_tell(a); + /* make a linked list of all packets */ switch( pkt->pkttype ) { case PKT_PUBLIC_CERT: case PKT_SECRET_CERT: - root = new_kbnode( pkt ); - pkt = m_alloc( sizeof *pkt ); - init_packet(pkt); - break; - - case PKT_USER_ID: - if( !root ) { - log_error("read_keyblock: orphaned user id\n" ); - rc = G10ERR_INV_KEYRING; /* or wrong kbpos */ + if( in_cert ) goto ready; - } - offset = last_offset; - /* append the user id */ - node = new_kbnode( pkt ); - if( !(n1=root->child) ) - root->child = node; - else { - for( ; n1->next; n1 = n1->next) - ; - n1->next = node; - } + in_cert = 1; + default: + kbpos->count++; + if( !root ) + root = new_kbnode( pkt ); + else + add_kbnode( root, new_kbnode( pkt ) ); pkt = m_alloc( sizeof *pkt ); init_packet(pkt); break; - - case PKT_SIGNATURE: - if( !root ) { - log_error("read_keyblock: no root for signature\n" ); - rc = G10ERR_INV_KEYRING; /* or wrong kbpos */ - break; - } - if( !root->child ) { - log_error("read_keyblock: no userid for signature\n" ); - rc = G10ERR_INV_KEYRING; - break; - } - /* goto the last user id */ - for(n1=root->child; n1->next; n1 = n1->next ) - ; - /* append the signature node */ - node = new_kbnode( pkt ); - if( !(n2=n1->child) ) - n1->child = node; - else { - for( ; n2->next; n2 = n2->next) - ; - n2->next = node; - } - pkt = m_alloc( sizeof *pkt ); - init_packet(pkt); - break; - - default: /* ignore all other packets. FIXME: we should not do this */ - free_packet( pkt ); - break; } } ready: - kbpos->last_block = rc == -1; /* flag, that this is the last block */ if( rc == -1 && root ) rc = 0; @@ -604,7 +553,6 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root ) release_kbnode( root ); else { *ret_root = root; - kbpos->length = offset - kbpos->offset; } free_packet( pkt ); m_free( pkt ); @@ -613,111 +561,175 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root ) } + /**************** - * Insert the keyblock described by ROOT into the keyring described - * by KBPOS. This actually appends the data to the keyfile. + * Peromf insert/delete/update operation. + * mode 1 = insert + * 2 = delete + * 3 = update */ static int -keyring_insert( KBPOS *kbpos, KBNODE root ) +keyring_copy( KBPOS *kbpos, int mode, KBNODE root ) { RESTBL *rentry; - IOBUF fp; - KBNODE kbctx, node; + IOBUF fp, newfp; int rc; + char *bakfname = NULL; + char *tmpfname = NULL; 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; - } + /* open the source file */ + fp = iobuf_open( rentry->fname ); + if( mode == 1 && !fp && errno == ENOENT ) { /* no file yet */ + KBNODE kbctx, node; - 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) ); + /* insert: create a new file */ + newfp = iobuf_create( rentry->fname ); + if( !newfp ) { + log_error("%s: can't create: %s\n", rentry->fname, strerror(errno)); + return G10ERR_OPEN_FILE; + } + + kbctx=NULL; + while( (node = walk_kbnode( root, &kbctx, 0 )) ) { + if( (rc = build_packet( newfp, node->pkt )) ) { + log_error("build_packet(%d) failed: %s\n", + node->pkt->pkttype, g10_errstr(rc) ); + iobuf_cancel(newfp); + return G10ERR_WRITE_FILE; + } + } + if( iobuf_close(newfp) ) { + log_error("%s: close failed: %s\n", rentry->fname, strerror(errno)); + return G10ERR_CLOSE_FILE; + } + if( chmod( rentry->fname, S_IRUSR | S_IWUSR ) ) { + log_error("%s: chmod failed: %s\n", + rentry->fname, strerror(errno) ); return G10ERR_WRITE_FILE; } + return 0; } - iobuf_close(fp); - - return 0; -} - -static int -keyring_delete( KBPOS *kbpos ) -{ - RESTBL *rentry; - IOBUF fp; - int rc; - u32 len; - int ctb; - - if( !(rentry = check_pos( kbpos )) ) - return G10ERR_GENERAL; - - - /* open the file for read/write */ - fp = iobuf_openrw( rentry->fname ); if( !fp ) { - log_error("can't open '%s' for writing\n", rentry->fname ); - return G10ERR_OPEN_FILE; + log_error("%s: can't open: %s\n", rentry->fname, strerror(errno) ); + rc = G10ERR_OPEN_FILE; + goto leave; } - if( iobuf_seek( fp, kbpos->offset ) ) { - log_error("can't seek to %lu: %s\n", kbpos->offset, g10_errstr(rc)); + /* create the new file */ + bakfname = m_alloc( strlen( rentry->fname ) + 2 ); + strcpy(stpcpy(bakfname,rentry->fname),"~"); + tmpfname = m_alloc( strlen( rentry->fname ) + 5 ); + strcpy(stpcpy(tmpfname,rentry->fname),".tmp"); + newfp = iobuf_create( tmpfname ); + if( !newfp ) { + log_error("%s: can't create: %s\n", tmpfname, strerror(errno) ); iobuf_close(fp); - return G10ERR_WRITE_FILE; + rc = G10ERR_OPEN_FILE; + goto leave; } - len = kbpos->length; - assert( len < 100000 ); /* there is a bug somewhere */ - /*log_debug("writing a dummy packet of length %lu\n", (ulong)len);*/ - - if( len < 2 ) - BUG(); - - if( len < 256 ) { - ctb = 0x80; - len -= 2; - } - else if( len < 65536 ) { - ctb = 0x81; - len -= 3; - } - else { - ctb = 0x82; - len -= 5; + if( mode == 1 ) { /* insert */ + /* copy everything to the new file */ + rc = copy_all_packets( fp, newfp ); + if( rc != -1 ) { + log_error("%s: copy to %s failed: %s\n", + rentry->fname, tmpfname, g10_errstr(rc) ); + iobuf_close(fp); + iobuf_cancel(newfp); + goto leave; + } + rc = 0; } - iobuf_put(fp, ctb ); - if( ctb & 2 ) { - iobuf_put(fp, len >> 24 ); - iobuf_put(fp, len >> 16 ); + + if( mode == 2 || mode == 3 ) { /* delete or update */ + /* copy first part to the new file */ + rc = copy_some_packets( fp, newfp, kbpos->offset ); + if( rc ) { /* should never get EOF here */ + log_error("%s: copy to %s failed: %s\n", + rentry->fname, tmpfname, g10_errstr(rc) ); + iobuf_close(fp); + iobuf_cancel(newfp); + goto leave; + } + /* skip this keyblock */ + assert( kbpos->count ); + rc = skip_some_packets( fp, kbpos->count ); + if( rc ) { + log_error("%s: skipping %u packets failed: %s\n", + rentry->fname, kbpos->count, g10_errstr(rc)); + iobuf_close(fp); + iobuf_cancel(newfp); + goto leave; + } } - if( ctb & 3 ) - iobuf_put(fp, len >> 8 ); - if( iobuf_put(fp, len ) ) { - iobuf_close(fp); - return G10ERR_WRITE_FILE; + + if( mode == 1 || mode == 3 ) { /* insert or update */ + KBNODE kbctx, node; + + /* append the new data */ + kbctx=NULL; + while( (node = walk_kbnode( root, &kbctx, 0 )) ) { + if( (rc = build_packet( newfp, node->pkt )) ) { + log_error("build_packet(%d) failed: %s\n", + node->pkt->pkttype, g10_errstr(rc) ); + iobuf_close(fp); + iobuf_cancel(newfp); + rc = G10ERR_WRITE_FILE; + goto leave; + } + } } - for( ; len; len-- ) - if( iobuf_put(fp, 0xff ) ) { + + if( mode == 2 || mode == 3 ) { /* delete or update */ + /* copy the rest */ + rc = copy_all_packets( fp, newfp ); + if( rc != -1 ) { + log_error("%s: copy to %s failed: %s\n", + rentry->fname, tmpfname, g10_errstr(rc) ); iobuf_close(fp); - return G10ERR_WRITE_FILE; + iobuf_cancel(newfp); + goto leave; } + rc = 0; + } + /* close both files */ iobuf_close(fp); + if( iobuf_close(newfp) ) { + log_error("%s: close failed: %s\n", tmpfname, strerror(errno) ); + rc = G10ERR_CLOSE_FILE; + goto leave; + } + /* if the new file is a secring, restrict the permissions */ + if( rentry->secret ) { + if( chmod( tmpfname, S_IRUSR | S_IWUSR ) ) { + log_error("%s: chmod failed: %s\n", + tmpfname, strerror(errno) ); + rc = G10ERR_WRITE_FILE; + goto leave; + } + } + /* rename and make backup file */ + if( rename( rentry->fname, bakfname ) ) { + log_error("%s: rename to %s failed: %s\n", + rentry->fname, bakfname, strerror(errno) ); + rc = G10ERR_RENAME_FILE; + goto leave; + } + if( rename( tmpfname, rentry->fname ) ) { + log_error("%s: rename to %s failed: %s\n", + tmpfname, rentry->fname,strerror(errno) ); + rc = G10ERR_RENAME_FILE; + goto leave; + } - return 0; + leave: + m_free(bakfname); + m_free(tmpfname); + return rc; } diff --git a/g10/sig-check.c b/g10/sig-check.c index fcc2a6948..cc133677f 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -248,9 +248,9 @@ check_key_signature( KBNODE root, KBNODE node, int *is_selfsig ) if( (rc=check_digest_algo(algo)) ) return rc; - unode = find_kbparent( root, node ); + unode = find_prev_kbnode( root, node, PKT_USER_ID ); - if( unode && unode->pkt->pkttype == PKT_USER_ID ) { + if( unode ) { PKT_user_id *uid = unode->pkt->pkt.user_id; if( is_selfsig ) { diff --git a/g10/sign.c b/g10/sign.c index 883a8d4f1..a59598c8f 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -527,7 +527,7 @@ check_all_keysigs( KBNODE keyblock ) int no_key = 0; int oth_err = 0; - for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) { + for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) { if( node->pkt->pkttype == PKT_SIGNATURE && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) { PKT_signature *sig = node->pkt->pkt.signature; @@ -579,7 +579,7 @@ remove_keysigs( KBNODE keyblock, int all ) int count; count = 0; - for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) { + for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) { if( ((node->flag & 7) || all ) && node->pkt->pkttype == PKT_SIGNATURE && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) { @@ -625,7 +625,7 @@ remove_keysigs( KBNODE keyblock, int all ) if( !yes ) return 0; - for( kbctx=NULL; (node=walk_kbtree2( keyblock, &kbctx, 1)) ; ) { + for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 1)) ; ) { if( node->flag & 128) delete_kbnode( keyblock, node ); } @@ -677,10 +677,7 @@ sign_key( const char *username, STRLIST locusr ) } /* get the keyid from the keyblock */ - for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) { - if( node->pkt->pkttype == PKT_PUBLIC_CERT ) - break; - } + node = find_kbnode( keyblock, PKT_PUBLIC_CERT ); if( !node ) { log_error("Oops; public key not found anymore!\n"); rc = G10ERR_GENERAL; @@ -719,7 +716,7 @@ sign_key( const char *username, STRLIST locusr ) u32 akeyid[2]; keyid_from_skc( skc_rover->skc, akeyid ); - for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) { + for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) { if( node->pkt->pkttype == PKT_SIGNATURE && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) { if( akeyid[0] == node->pkt->pkt.signature->keyid[0] @@ -744,7 +741,7 @@ sign_key( const char *username, STRLIST locusr ) for( skc_rover = skc_list; skc_rover; skc_rover = skc_rover->next ) { if( skc_rover->mark ) continue; - for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) { + for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) { if( node->pkt->pkttype == PKT_USER_ID ) { if( sign_it_p( pkc, node->pkt->pkt.user_id ) ) { PACKET *pkt; @@ -763,7 +760,7 @@ sign_key( const char *username, STRLIST locusr ) pkt = m_alloc_clear( sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = sig; - add_kbnode_as_child( node, new_kbnode( pkt ) ); + insert_kbnode( node, new_kbnode(pkt), PKT_USER_ID ); } } } @@ -789,7 +786,7 @@ edit_keysigs( const char *username ) { int rc = 0; KBNODE keyblock = NULL; - KBNODE kbctx, node; + KBNODE node; KBPOS kbpos; PKT_public_cert *pkc; u32 pkc_keyid[2]; @@ -809,10 +806,7 @@ edit_keysigs( const char *username ) } /* get the keyid from the keyblock */ - for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) { - if( node->pkt->pkttype == PKT_PUBLIC_CERT ) - break; - } + node = find_kbnode( keyblock, PKT_PUBLIC_CERT ); if( !node ) { log_error("Oops; public key not found anymore!\n"); rc = G10ERR_GENERAL; @@ -855,7 +849,7 @@ change_passphrase( const char *username ) { int rc = 0; KBNODE keyblock = NULL; - KBNODE kbctx, node; + KBNODE node; KBPOS kbpos; PKT_secret_cert *skc; u32 skc_keyid[2]; @@ -877,10 +871,7 @@ change_passphrase( const char *username ) } /* get the keyid from the keyblock */ - for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) { - if( node->pkt->pkttype == PKT_SECRET_CERT ) - break; - } + node = find_kbnode( keyblock, PKT_SECRET_CERT ); if( !node ) { log_error("Oops; secret key not found anymore!\n"); rc = G10ERR_GENERAL; diff --git a/g10/trustdb.c b/g10/trustdb.c index d317a665a..3f567e887 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -1090,7 +1090,7 @@ check_sigs( KBNODE keyblock, int *selfsig_okay ) LOCAL_ID_INFO *dups = NULL; *selfsig_okay = 0; - for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) { + for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx,0)) ; ) { if( node->pkt->pkttype == PKT_SIGNATURE && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) { int selfsig; @@ -1190,7 +1190,7 @@ build_sigrecs( ulong pubkeyid ) rec.rectype = RECTYPE_SIG; i = 0; rnum = rnum2 = 0; - for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) { + for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) { /* insert sigs which are not a selfsig nor a duplicate */ if( (node->flag & 1) && !(node->flag & 4) ) { assert( node->pkt->pkttype == PKT_SIGNATURE ); diff --git a/include/errors.h b/include/errors.h index fcae69ec4..36aff5bd6 100644 --- a/include/errors.h +++ b/include/errors.h @@ -55,5 +55,8 @@ #define G10ERR_TRUSTDB 33 /* a problem with the trustdb */ #define G10ERR_BAD_CERT 34 /* bad certicate */ #define G10ERR_INV_USER_ID 35 +#define G10ERR_CLOSE_FILE 36 +#define G10ERR_RENAME_FILE 37 +#define G10ERR_DELETE_FILE 38 #endif /*G10_ERRORS_H*/ diff --git a/include/i18n.h b/include/i18n.h index a75f3c40f..d43c078a6 100644 --- a/include/i18n.h +++ b/include/i18n.h @@ -21,6 +21,10 @@ #ifndef G10_I18N_H #define G10_I18N_H +#ifdef HAVE_LOCALE_H + #include <locale.h> /* suggested by Ernst Molitor */ +#endif + #ifdef HAVE_LIBINTL #include <libintl.h> #define _(a) gettext (a) diff --git a/include/iobuf.h b/include/iobuf.h index e5ce81a3f..a57d7a9ab 100644 --- a/include/iobuf.h +++ b/include/iobuf.h @@ -88,6 +88,7 @@ ulong iobuf_tell( IOBUF a ); int iobuf_seek( IOBUF a, ulong newpos ); int iobuf_readbyte(IOBUF a); +int iobuf_read(IOBUF a, byte *buf, unsigned buflen ); int iobuf_writebyte(IOBUF a, unsigned c); int iobuf_write(IOBUF a, byte *buf, unsigned buflen ); int iobuf_writestr(IOBUF a, const char *buf ); diff --git a/include/mpi.h b/include/mpi.h index 1354dda4c..87bb05363 100644 --- a/include/mpi.h +++ b/include/mpi.h @@ -132,6 +132,9 @@ int mpi_gcd( MPI g, MPI a, MPI b ); void mpi_pow( MPI w, MPI u, MPI v); void mpi_powm( MPI res, MPI base, MPI exp, MPI mod); +/*-- mpi-mpow.c --*/ +void mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI mod); + /*-- mpi-cmp.c --*/ int mpi_cmp_ui( MPI u, ulong v ); int mpi_cmp( MPI u, MPI v ); diff --git a/mpi/Makefile.am b/mpi/Makefile.am index 1c32e1312..2801a7519 100644 --- a/mpi/Makefile.am +++ b/mpi/Makefile.am @@ -24,6 +24,7 @@ libmpi_a_SOURCES = longlong.h \ mpi-inv.c \ mpi-mul.c \ mpi-pow.c \ + mpi-mpow.c \ mpi-scan.c \ mpicoder.c \ mpih-cmp.c \ diff --git a/mpi/Makefile.in b/mpi/Makefile.in index aae7160c0..bcbbc6416 100644 --- a/mpi/Makefile.in +++ b/mpi/Makefile.in @@ -106,6 +106,7 @@ libmpi_a_SOURCES = longlong.h \ mpi-inv.c \ mpi-mul.c \ mpi-pow.c \ + mpi-mpow.c \ mpi-scan.c \ mpicoder.c \ mpih-cmp.c \ @@ -138,13 +139,13 @@ LIBS = @LIBS@ libmpi_a_DEPENDENCIES = mpih-mul1.o mpih-mul2.o mpih-mul3.o mpih-add1.o \ mpih-sub1.o mpih-shift.o libmpi_a_OBJECTS = mpi-add.o mpi-bit.o mpi-cmp.o mpi-div.o mpi-gcd.o \ -mpi-inv.o mpi-mul.o mpi-pow.o mpi-scan.o mpicoder.o mpih-cmp.o \ -mpih-add.o mpih-sub.o mpih-div.o mpih-mul.o mpiutil.o +mpi-inv.o mpi-mul.o mpi-pow.o mpi-mpow.o mpi-scan.o mpicoder.o \ +mpih-cmp.o mpih-add.o mpih-sub.o mpih-div.o mpih-mul.o mpiutil.o AR = ar CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ -DIST_COMMON = Makefile.am Makefile.in +DIST_COMMON = ChangeLog Makefile.am Makefile.in DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) @@ -152,10 +153,10 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = tar GZIP = --best DEP_FILES = .deps/mpi-add.P .deps/mpi-bit.P .deps/mpi-cmp.P \ -.deps/mpi-div.P .deps/mpi-gcd.P .deps/mpi-inv.P .deps/mpi-mul.P \ -.deps/mpi-pow.P .deps/mpi-scan.P .deps/mpicoder.P .deps/mpih-add.P \ -.deps/mpih-cmp.P .deps/mpih-div.P .deps/mpih-mul.P .deps/mpih-sub.P \ -.deps/mpiutil.P +.deps/mpi-div.P .deps/mpi-gcd.P .deps/mpi-inv.P .deps/mpi-mpow.P \ +.deps/mpi-mul.P .deps/mpi-pow.P .deps/mpi-scan.P .deps/mpicoder.P \ +.deps/mpih-add.P .deps/mpih-cmp.P .deps/mpih-div.P .deps/mpih-mul.P \ +.deps/mpih-sub.P .deps/mpiutil.P SOURCES = $(libmpi_a_SOURCES) OBJECTS = $(libmpi_a_OBJECTS) diff --git a/mpi/config.links b/mpi/config.links index 923e18b0d..cf370e054 100644 --- a/mpi/config.links +++ b/mpi/config.links @@ -10,7 +10,7 @@ test -d ./mpi || mkdir ./mpi echo '/* created by config.links - do not edit */' >./mpi/asm-syntax.h case "${target}" in - i[345]86*-*-linuxaout* | i[345]86*-*-linuxoldld* | i[345]86*-*-*bsd*) + i[34]86*-*-linuxaout* | i[34]86*-*-linuxoldld* | i[34]86*-*-*bsd*) echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h path="i386" @@ -20,14 +20,14 @@ case "${target}" in cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h path="i586 i386" ;; - i[3456]86*-*-*) + i[34]86*-*-*) echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h path="i386" ;; i[56]86*-*-* | pentium-*-* | pentiumpro-*-*) echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h - cat $srcdir/mpi/i586/syntax.h >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h path="i586 i386" ;; alpha*-*-*) diff --git a/mpi/i586/README b/mpi/i586/README new file mode 100644 index 000000000..d73b08268 --- /dev/null +++ b/mpi/i586/README @@ -0,0 +1,26 @@ +This directory contains mpn functions optimized for Intel Pentium +processors. + +RELEVANT OPTIMIZATION ISSUES + +1. Pentium doesn't allocate cache lines on writes, unlike most other modern +processors. Since the functions in the mpn class do array writes, we have to +handle allocating the destination cache lines by reading a word from it in the +loops, to achieve the best performance. + +2. Pairing of memory operations requires that the two issued operations refer +to different cache banks. The simplest way to insure this is to read/write +two words from the same object. If we make operations on different objects, +they might or might not be to the same cache bank. + +STATUS + +1. mpn_lshift and mpn_rshift run at about 6 cycles/limb, but the Pentium +documentation indicates that they should take only 43/8 = 5.375 cycles/limb, +or 5 cycles/limb asymptotically. + +2. mpn_add_n and mpn_sub_n run at asymptotically 2 cycles/limb. Due to loop +overhead and other delays (cache refill?), they run at or near 2.5 cycles/limb. + +3. mpn_mul_1, mpn_addmul_1, mpn_submul_1 all run 1 cycle faster than they +should... diff --git a/mpi/i586/distfiles b/mpi/i586/distfiles new file mode 100644 index 000000000..951480fde --- /dev/null +++ b/mpi/i586/distfiles @@ -0,0 +1,8 @@ +mpih-add1.S +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +mpih-shift.S +mpih-sub1.S +README + diff --git a/mpi/i586/mpih-add1.S b/mpi/i586/mpih-add1.S new file mode 100644 index 000000000..e9883285d --- /dev/null +++ b/mpi/i586/mpih-add1.S @@ -0,0 +1,134 @@ +/* i80586 add_n -- Add two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1996 Free Software Foundation, Inc. + * + * This file is part of G10. + * + * G10 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * G10 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_add_n( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_ptr_t s2_ptr, (sp + 12) + * mpi_size_t size) (sp + 16) + */ + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(mpihelp_add_n) +C_SYMBOL_NAME(mpihelp_add_n:) + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl 20(%esp),%edi /* res_ptr */ + movl 24(%esp),%esi /* s1_ptr */ + movl 28(%esp),%ebp /* s2_ptr */ + movl 32(%esp),%ecx /* size */ + + movl (%ebp),%ebx + + decl %ecx + movl %ecx,%edx + shrl $3,%ecx + andl $7,%edx + testl %ecx,%ecx /* zero carry flag */ + jz Lend + pushl %edx + + ALIGN (3) +Loop: movl 28(%edi),%eax /* fetch destination cache line */ + leal 32(%edi),%edi + +L1: movl (%esi),%eax + movl 4(%esi),%edx + adcl %ebx,%eax + movl 4(%ebp),%ebx + adcl %ebx,%edx + movl 8(%ebp),%ebx + movl %eax,-32(%edi) + movl %edx,-28(%edi) + +L2: movl 8(%esi),%eax + movl 12(%esi),%edx + adcl %ebx,%eax + movl 12(%ebp),%ebx + adcl %ebx,%edx + movl 16(%ebp),%ebx + movl %eax,-24(%edi) + movl %edx,-20(%edi) + +L3: movl 16(%esi),%eax + movl 20(%esi),%edx + adcl %ebx,%eax + movl 20(%ebp),%ebx + adcl %ebx,%edx + movl 24(%ebp),%ebx + movl %eax,-16(%edi) + movl %edx,-12(%edi) + +L4: movl 24(%esi),%eax + movl 28(%esi),%edx + adcl %ebx,%eax + movl 28(%ebp),%ebx + adcl %ebx,%edx + movl 32(%ebp),%ebx + movl %eax,-8(%edi) + movl %edx,-4(%edi) + + leal 32(%esi),%esi + leal 32(%ebp),%ebp + decl %ecx + jnz Loop + + popl %edx +Lend: + decl %edx /* test %edx w/o clobbering carry */ + js Lend2 + incl %edx +Loop2: + leal 4(%edi),%edi + movl (%esi),%eax + adcl %ebx,%eax + movl 4(%ebp),%ebx + movl %eax,-4(%edi) + leal 4(%esi),%esi + leal 4(%ebp),%ebp + decl %edx + jnz Loop2 +Lend2: + movl (%esi),%eax + adcl %ebx,%eax + movl %eax,(%edi) + + sbbl %eax,%eax + negl %eax + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + + diff --git a/mpi/i586/mpih-mul1.S b/mpi/i586/mpih-mul1.S new file mode 100644 index 000000000..c0bedec0a --- /dev/null +++ b/mpi/i586/mpih-mul1.S @@ -0,0 +1,89 @@ +/* i80586 mul_1 -- Multiply a limb vector with a limb and store + * the result in a second limb vector. + * Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc. + * + * This file is part of G10. + * + * G10 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * G10 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_mul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(mpihelp_mul_1) +C_SYMBOL_NAME(mpihelp_mul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) + +Loop: INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + + INSN1(mul,l ,R(s2_limb)) + + INSN2(add,l ,R(ebx),R(eax)) + + INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx)) + INSN1(inc,l ,R(size)) + + INSN2(mov,l ,R(ebx),R(edx)) + INSN1(jnz, ,Loop) + + INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),R(ebx)) + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret + diff --git a/mpi/i586/mpih-mul2.S b/mpi/i586/mpih-mul2.S new file mode 100644 index 000000000..6b5646239 --- /dev/null +++ b/mpi/i586/mpih-mul2.S @@ -0,0 +1,94 @@ +/* i80586 addmul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * Copyright (c) 1997 by Werner Koch (dd9jn) + * Copyright (C) 1992, 1994 Free Software Foundation, Inc. + * + * This file is part of G10. + * + * G10 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * G10 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_addmul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(mpihelp_addmul_1) +C_SYMBOL_NAME(mpihelp_addmul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) + +Loop: INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + + INSN1(mul,l ,R(s2_limb)) + + INSN2(add,l ,R(eax),R(ebx)) + INSN2(mov,l ,R(ebx),MEM_INDEX(res_ptr,size,4)) + + INSN2(adc,l ,R(edx),$0) + INSN2(add,l ,R(ebx),R(eax)) + + INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx)) + INSN1(inc,l ,R(size)) + + INSN2(mov,l ,R(ebx),R(edx)) + INSN1(jnz, ,Loop) + + INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),R(ebx)) + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret + diff --git a/mpi/i586/mpih-mul3.S b/mpi/i586/mpih-mul3.S new file mode 100644 index 000000000..69b7f4672 --- /dev/null +++ b/mpi/i586/mpih-mul3.S @@ -0,0 +1,94 @@ +/* i80586 submul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * Copyright (c) 1997 by Werner Koch (dd9jn) + * Copyright (C) 1992, 1994 Free Software Foundation, Inc. + * + * This file is part of G10. + * + * G10 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * G10 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_submul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(mpihelp_submul_1) +C_SYMBOL_NAME(mpihelp_submul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) + +Loop: INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + + INSN1(mul,l ,R(s2_limb)) + + INSN2(add,l ,R(eax),R(ebx)) + INSN2(mov,l ,R(ebx),MEM_INDEX(res_ptr,size,4)) + + INSN2(adc,l ,R(edx),$0) + INSN2(sub,l ,R(ebx),R(eax)) + + INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx)) + INSN1(inc,l ,R(size)) + + INSN2(mov,l ,R(ebx),R(edx)) + INSN1(jnz, ,Loop) + + INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),R(ebx)) + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret + diff --git a/mpi/i586/mpih-shift.S b/mpi/i586/mpih-shift.S new file mode 100644 index 000000000..9f1563810 --- /dev/null +++ b/mpi/i586/mpih-shift.S @@ -0,0 +1,426 @@ +/* i80586 rshift, lshift + * Copyright (c) 1997 by Werner Koch (dd9jn) + * Copyright (C) 1992, 1994 Free Software Foundation, Inc. + * + * This file is part of G10. + * + * G10 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * G10 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_lshift( mpi_ptr_t wp, (sp + 4) + * mpi_ptr_t up, (sp + 8) + * mpi_size_t usize, (sp + 12) + * unsigned cnt) (sp + 16) + */ + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(mpihelp_lshift) +C_SYMBOL_NAME(mpihelp_lshift:) + + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl 20(%esp),%edi /* res_ptr */ + movl 24(%esp),%esi /* s_ptr */ + movl 28(%esp),%ebp /* size */ + movl 32(%esp),%ecx /* cnt */ + +/* We can use faster code for shift-by-1 under certain conditions. */ + cmp $1,%ecx + jne Lnormal + leal 4(%esi),%eax + cmpl %edi,%eax + jnc Lspecial /* jump if s_ptr + 1 >= res_ptr */ + leal (%esi,%ebp,4),%eax + cmpl %eax,%edi + jnc Lspecial /* jump if res_ptr >= s_ptr + size */ + +Lnormal: + leal -4(%edi,%ebp,4),%edi + leal -4(%esi,%ebp,4),%esi + + movl (%esi),%edx + subl $4,%esi + xorl %eax,%eax + shldl %cl,%edx,%eax /* compute carry limb */ + pushl %eax /* push carry limb onto stack */ + + decl %ebp + pushl %ebp + shrl $3,%ebp + jz Lend + + movl (%edi),%eax /* fetch destination cache line */ + + ALIGN (2) +Loop: movl -28(%edi),%eax /* fetch destination cache line */ + movl %edx,%ebx + + movl (%esi),%eax + movl -4(%esi),%edx + shldl %cl,%eax,%ebx + shldl %cl,%edx,%eax + movl %ebx,(%edi) + movl %eax,-4(%edi) + + movl -8(%esi),%ebx + movl -12(%esi),%eax + shldl %cl,%ebx,%edx + shldl %cl,%eax,%ebx + movl %edx,-8(%edi) + movl %ebx,-12(%edi) + + movl -16(%esi),%edx + movl -20(%esi),%ebx + shldl %cl,%edx,%eax + shldl %cl,%ebx,%edx + movl %eax,-16(%edi) + movl %edx,-20(%edi) + + movl -24(%esi),%eax + movl -28(%esi),%edx + shldl %cl,%eax,%ebx + shldl %cl,%edx,%eax + movl %ebx,-24(%edi) + movl %eax,-28(%edi) + + subl $32,%esi + subl $32,%edi + decl %ebp + jnz Loop + +Lend: popl %ebp + andl $7,%ebp + jz Lend2 +Loop2: movl (%esi),%eax + shldl %cl,%eax,%edx + movl %edx,(%edi) + movl %eax,%edx + subl $4,%esi + subl $4,%edi + decl %ebp + jnz Loop2 + +Lend2: shll %cl,%edx /* compute least significant limb */ + movl %edx,(%edi) /* store it */ + + popl %eax /* pop carry limb */ + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + +/* We loop from least significant end of the arrays, which is only + permissable if the source and destination don't overlap, since the + function is documented to work for overlapping source and destination. +*/ + +Lspecial: + movl (%esi),%edx + addl $4,%esi + + decl %ebp + pushl %ebp + shrl $3,%ebp + + addl %edx,%edx + incl %ebp + decl %ebp + jz LLend + + movl (%edi),%eax /* fetch destination cache line */ + + ALIGN (2) +LLoop: movl 28(%edi),%eax /* fetch destination cache line */ + movl %edx,%ebx + + movl (%esi),%eax + movl 4(%esi),%edx + adcl %eax,%eax + movl %ebx,(%edi) + adcl %edx,%edx + movl %eax,4(%edi) + + movl 8(%esi),%ebx + movl 12(%esi),%eax + adcl %ebx,%ebx + movl %edx,8(%edi) + adcl %eax,%eax + movl %ebx,12(%edi) + + movl 16(%esi),%edx + movl 20(%esi),%ebx + adcl %edx,%edx + movl %eax,16(%edi) + adcl %ebx,%ebx + movl %edx,20(%edi) + + movl 24(%esi),%eax + movl 28(%esi),%edx + adcl %eax,%eax + movl %ebx,24(%edi) + adcl %edx,%edx + movl %eax,28(%edi) + + leal 32(%esi),%esi /* use leal not to clobber carry */ + leal 32(%edi),%edi + decl %ebp + jnz LLoop + +LLend: popl %ebp + sbbl %eax,%eax /* save carry in %eax */ + andl $7,%ebp + jz LLend2 + addl %eax,%eax /* restore carry from eax */ +LLoop2: movl %edx,%ebx + movl (%esi),%edx + adcl %edx,%edx + movl %ebx,(%edi) + + leal 4(%esi),%esi /* use leal not to clobber carry */ + leal 4(%edi),%edi + decl %ebp + jnz LLoop2 + + jmp LL1 +LLend2: addl %eax,%eax /* restore carry from eax */ +LL1: movl %edx,(%edi) /* store last limb */ + + sbbl %eax,%eax + negl %eax + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + + + + +/******************* + * mpi_limb_t + * mpihelp_rshift( mpi_ptr_t wp, (sp + 4) + * mpi_ptr_t up, (sp + 8) + * mpi_size_t usize, (sp + 12) + * unsigned cnt) (sp + 16) + */ + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(mpihelp_rshift) +C_SYMBOL_NAME(mpihelp_rshift:) + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl 20(%esp),%edi /* res_ptr */ + movl 24(%esp),%esi /* s_ptr */ + movl 28(%esp),%ebp /* size */ + movl 32(%esp),%ecx /* cnt */ + +/* We can use faster code for shift-by-1 under certain conditions. */ + cmp $1,%ecx + jne Rnormal + leal 4(%edi),%eax + cmpl %esi,%eax + jnc Rspecial /* jump if res_ptr + 1 >= s_ptr */ + leal (%edi,%ebp,4),%eax + cmpl %eax,%esi + jnc Rspecial /* jump if s_ptr >= res_ptr + size */ + +Rnormal: + movl (%esi),%edx + addl $4,%esi + xorl %eax,%eax + shrdl %cl,%edx,%eax /* compute carry limb */ + pushl %eax /* push carry limb onto stack */ + + decl %ebp + pushl %ebp + shrl $3,%ebp + jz Rend + + movl (%edi),%eax /* fetch destination cache line */ + + ALIGN (2) +Roop: movl 28(%edi),%eax /* fetch destination cache line */ + movl %edx,%ebx + + movl (%esi),%eax + movl 4(%esi),%edx + shrdl %cl,%eax,%ebx + shrdl %cl,%edx,%eax + movl %ebx,(%edi) + movl %eax,4(%edi) + + movl 8(%esi),%ebx + movl 12(%esi),%eax + shrdl %cl,%ebx,%edx + shrdl %cl,%eax,%ebx + movl %edx,8(%edi) + movl %ebx,12(%edi) + + movl 16(%esi),%edx + movl 20(%esi),%ebx + shrdl %cl,%edx,%eax + shrdl %cl,%ebx,%edx + movl %eax,16(%edi) + movl %edx,20(%edi) + + movl 24(%esi),%eax + movl 28(%esi),%edx + shrdl %cl,%eax,%ebx + shrdl %cl,%edx,%eax + movl %ebx,24(%edi) + movl %eax,28(%edi) + + addl $32,%esi + addl $32,%edi + decl %ebp + jnz Roop + +Rend: popl %ebp + andl $7,%ebp + jz Rend2 +Roop2: movl (%esi),%eax + shrdl %cl,%eax,%edx /* compute result limb */ + movl %edx,(%edi) + movl %eax,%edx + addl $4,%esi + addl $4,%edi + decl %ebp + jnz Roop2 + +Rend2: shrl %cl,%edx /* compute most significant limb */ + movl %edx,(%edi) /* store it */ + + popl %eax /* pop carry limb */ + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + +/* We loop from least significant end of the arrays, which is only + permissable if the source and destination don't overlap, since the + function is documented to work for overlapping source and destination. +*/ + +Rspecial: + leal -4(%edi,%ebp,4),%edi + leal -4(%esi,%ebp,4),%esi + + movl (%esi),%edx + subl $4,%esi + + decl %ebp + pushl %ebp + shrl $3,%ebp + + shrl $1,%edx + incl %ebp + decl %ebp + jz RLend + + movl (%edi),%eax /* fetch destination cache line */ + + ALIGN (2) +RLoop: movl -28(%edi),%eax /* fetch destination cache line */ + movl %edx,%ebx + + movl (%esi),%eax + movl -4(%esi),%edx + rcrl $1,%eax + movl %ebx,(%edi) + rcrl $1,%edx + movl %eax,-4(%edi) + + movl -8(%esi),%ebx + movl -12(%esi),%eax + rcrl $1,%ebx + movl %edx,-8(%edi) + rcrl $1,%eax + movl %ebx,-12(%edi) + + movl -16(%esi),%edx + movl -20(%esi),%ebx + rcrl $1,%edx + movl %eax,-16(%edi) + rcrl $1,%ebx + movl %edx,-20(%edi) + + movl -24(%esi),%eax + movl -28(%esi),%edx + rcrl $1,%eax + movl %ebx,-24(%edi) + rcrl $1,%edx + movl %eax,-28(%edi) + + leal -32(%esi),%esi /* use leal not to clobber carry */ + leal -32(%edi),%edi + decl %ebp + jnz RLoop + +RLend: popl %ebp + sbbl %eax,%eax /* save carry in %eax */ + andl $7,%ebp + jz RLend2 + addl %eax,%eax /* restore carry from eax */ +RLoop2: movl %edx,%ebx + movl (%esi),%edx + rcrl $1,%edx + movl %ebx,(%edi) + + leal -4(%esi),%esi /* use leal not to clobber carry */ + leal -4(%edi),%edi + decl %ebp + jnz RLoop2 + + jmp RL1 +RLend2: addl %eax,%eax /* restore carry from eax */ +RL1: movl %edx,(%edi) /* store last limb */ + + movl $0,%eax + rcrl $1,%eax + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + diff --git a/mpi/i586/mpih-sub1.S b/mpi/i586/mpih-sub1.S new file mode 100644 index 000000000..1f5c0bfdd --- /dev/null +++ b/mpi/i586/mpih-sub1.S @@ -0,0 +1,143 @@ +/* i80586 sub_n -- Sub two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc. + * Copyright (c) 1997 by Werner Koch (dd9jn) + * + * This file is part of G10. + * + * G10 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * G10 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_sub_n( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_ptr_t s2_ptr, (sp + 12) + * mpi_size_t size) (sp + 16) + */ + + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(mpihelp_sub_n) +C_SYMBOL_NAME(mpihelp_sub_n:) + + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl 20(%esp),%edi /* res_ptr */ + movl 24(%esp),%esi /* s1_ptr */ + movl 28(%esp),%ebp /* s2_ptr */ + movl 32(%esp),%ecx /* size */ + + movl (%ebp),%ebx + + decl %ecx + movl %ecx,%edx + shrl $3,%ecx + andl $7,%edx + testl %ecx,%ecx /* zero carry flag */ + jz Lend + pushl %edx + + ALIGN (3) +Loop: movl 28(%edi),%eax /* fetch destination cache line */ + leal 32(%edi),%edi + +L1: movl (%esi),%eax + movl 4(%esi),%edx + sbbl %ebx,%eax + movl 4(%ebp),%ebx + sbbl %ebx,%edx + movl 8(%ebp),%ebx + movl %eax,-32(%edi) + movl %edx,-28(%edi) + +L2: movl 8(%esi),%eax + movl 12(%esi),%edx + sbbl %ebx,%eax + movl 12(%ebp),%ebx + sbbl %ebx,%edx + movl 16(%ebp),%ebx + movl %eax,-24(%edi) + movl %edx,-20(%edi) + +L3: movl 16(%esi),%eax + movl 20(%esi),%edx + sbbl %ebx,%eax + movl 20(%ebp),%ebx + sbbl %ebx,%edx + movl 24(%ebp),%ebx + movl %eax,-16(%edi) + movl %edx,-12(%edi) + +L4: movl 24(%esi),%eax + movl 28(%esi),%edx + sbbl %ebx,%eax + movl 28(%ebp),%ebx + sbbl %ebx,%edx + movl 32(%ebp),%ebx + movl %eax,-8(%edi) + movl %edx,-4(%edi) + + leal 32(%esi),%esi + leal 32(%ebp),%ebp + decl %ecx + jnz Loop + + popl %edx +Lend: + decl %edx /* test %edx w/o clobbering carry */ + js Lend2 + incl %edx +Loop2: + leal 4(%edi),%edi + movl (%esi),%eax + sbbl %ebx,%eax + movl 4(%ebp),%ebx + movl %eax,-4(%edi) + leal 4(%esi),%esi + leal 4(%ebp),%ebp + decl %edx + jnz Loop2 +Lend2: + movl (%esi),%eax + sbbl %ebx,%eax + movl %eax,(%edi) + + sbbl %eax,%eax + negl %eax + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + diff --git a/mpi/mpi-inv.c b/mpi/mpi-inv.c index 28cde00b6..53ef356b3 100644 --- a/mpi/mpi-inv.c +++ b/mpi/mpi-inv.c @@ -76,7 +76,7 @@ mpi_invm( MPI x, MPI a, MPI n ) mpi_free(t3); mpi_free(u); mpi_free(v); - #else + #elif 0 /* Extended Euclid's algorithm (See TAOPC Vol II, 4.5.2, Alg X) * modified according to Michael Penk's solution for Exercice 35 */ @@ -156,6 +156,107 @@ mpi_invm( MPI x, MPI a, MPI n ) mpi_free(t1); mpi_free(t2); mpi_free(t3); + #else + /* Extended Euclid's algorithm (See TAOPC Vol II, 4.5.2, Alg X) + * modified according to Michael Penk's solution for Exercice 35 + * with further enhancement */ + MPI u, v, u1, u2=NULL, u3, v1, v2=NULL, v3, t1, t2=NULL, t3; + unsigned k; + int sign; + int odd ; + + u = mpi_copy(a); + v = mpi_copy(n); + for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) { + mpi_rshift(u, u, 1); + mpi_rshift(v, v, 1); + } + odd = mpi_test_bit(v,0); + + u1 = mpi_alloc_set_ui(1); + if( !odd ) + u2 = mpi_alloc_set_ui(0); + u3 = mpi_copy(u); + v1 = mpi_copy(v); + if( !odd ) { + v2 = mpi_alloc( mpi_get_nlimbs(u) ); + mpi_sub( v2, u1, u ); /* U is used as const 1 */ + } + v3 = mpi_copy(v); + if( mpi_test_bit(u, 0) ) { /* u is odd */ + t1 = mpi_alloc_set_ui(0); + if( !odd ) { + t2 = mpi_alloc_set_ui(1); t2->sign = 1; + } + t3 = mpi_copy(v); t3->sign = !t3->sign; + goto Y4; + } + else { + t1 = mpi_alloc_set_ui(1); + if( !odd ) + t2 = mpi_alloc_set_ui(0); + t3 = mpi_copy(u); + } + do { + do { + if( !odd ) { + if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */ + mpi_add(t1, t1, v); + mpi_sub(t2, t2, u); + } + mpi_rshift(t1, t1, 1); + mpi_rshift(t2, t2, 1); + mpi_rshift(t3, t3, 1); + } + else { + if( mpi_test_bit(t1, 0) ) + mpi_add(t1, t1, v); + mpi_rshift(t1, t1, 1); + mpi_rshift(t3, t3, 1); + } + Y4: + } while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */ + + if( !t3->sign ) { + mpi_set(u1, t1); + if( !odd ) + mpi_set(u2, t2); + mpi_set(u3, t3); + } + else { + mpi_sub(v1, v, t1); + sign = u->sign; u->sign = !u->sign; + if( !odd ) + mpi_sub(v2, u, t2); + u->sign = sign; + sign = t3->sign; t3->sign = !t3->sign; + mpi_set(v3, t3); + t3->sign = sign; + } + mpi_sub(t1, u1, v1); + if( !odd ) + mpi_sub(t2, u2, v2); + mpi_sub(t3, u3, v3); + if( t1->sign ) { + mpi_add(t1, t1, v); + if( !odd ) + mpi_sub(t2, t2, u); + } + } while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */ + /* mpi_lshift( u3, k ); */ + mpi_set(x, u1); + + mpi_free(u1); + mpi_free(v1); + mpi_free(t1); + if( !odd ) { + mpi_free(u2); + mpi_free(v2); + mpi_free(t2); + } + mpi_free(u3); + mpi_free(v3); + mpi_free(t3); #endif } diff --git a/mpi/mpi-mpow.c b/mpi/mpi-mpow.c new file mode 100644 index 000000000..5ac3c6399 --- /dev/null +++ b/mpi/mpi-mpow.c @@ -0,0 +1,119 @@ +/* mpi-mpow.c - MPI functions + * Copyright (c) 1998 by Werner Koch (dd9jn) + * + * This file is part of G10. + * + * G10 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * G10 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" +#include <assert.h> + +static int +build_index( MPI *exparray, int k, int i, int t ) +{ + int j, bitno; + int index = 0; + + bitno = t-i; + for(j=k-1; j >= 0; j-- ) { + index <<= 1; + if( mpi_test_bit( exparray[j], bitno ) ) + index |= 1; + } + /*log_debug("t=%d i=%d index=%d\n", t, i, index );*/ + return index; +} + +/**************** + * RES = (BASE[0] ^ EXP[0]) * (BASE[1] ^ EXP[1]) * ... * mod M + */ +void +mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI m) +{ + int k; /* number of elements */ + int t; /* bit size of largest exponent */ + int i, j, idx; + MPI *G; /* table with precomputed values of size 2^k */ + MPI tmp; + + for(k=0; basearray[k]; k++ ) + ; + assert(k); + for(t=0, i=0; (tmp=exparray[i]); i++ ) { + /*log_mpidump("exp: ", tmp );*/ + j = mpi_get_nbits(tmp); + if( j > t ) + t = j; + } + /*log_mpidump("mod: ", m );*/ + assert(i==k); + assert(t); + assert( k < 10 ); + + G = m_alloc_clear( (1<<k) * sizeof *G ); + #if 0 + /* do the precomputation */ + G[0] = mpi_alloc_set_ui( 1 ); + for(i=1; i < (1<<k); i++ ) { + for(j=0; j < k; j++ ) { + if( (i & (1<<j) ) ) { + if( !G[i] ) + G[i] = mpi_copy( basearray[j] ); + else + mpi_mulm( G[i], G[i], basearray[j], m ); + } + } + if( !G[i] ) + G[i] = mpi_alloc(0); + } + #endif + /* and calculate */ + tmp = mpi_alloc( mpi_get_nlimbs(m)+1 ); + mpi_set_ui( res, 1 ); + for(i = 1; i <= t; i++ ) { + mpi_mulm(tmp, res, res, m ); + idx = build_index( exparray, k, i, t ); + assert( idx >= 0 && idx < (1<<k) ); + if( !G[idx] ) { + if( !idx ) + G[0] = mpi_alloc_set_ui( 1 ); + else { + for(j=0; j < k; j++ ) { + if( (idx & (1<<j) ) ) { + if( !G[idx] ) + G[idx] = mpi_copy( basearray[j] ); + else + mpi_mulm( G[idx], G[idx], basearray[j], m ); + } + } + if( !G[idx] ) + G[idx] = mpi_alloc(0); + } + } + mpi_mulm(res, tmp, G[idx], m ); + } + + /* cleanup */ + m_free(tmp); + for(i=0; i < (1<<k); i++ ) + mpi_free(G[i]); + m_free(G); +} + diff --git a/po/ChangeLog b/po/ChangeLog index e69de29bb..1d2526595 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -0,0 +1,5 @@ +Tue Feb 10 11:57:23 1998 Werner Koch (wk@frodo) + + * ddd/hhhh: + + diff --git a/tools/Makefile.in b/tools/Makefile.in index 0594ccd4d..add8db5f5 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -119,7 +119,7 @@ bftest_LDFLAGS = CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ -DIST_COMMON = Makefile.am Makefile.in +DIST_COMMON = ChangeLog Makefile.am Makefile.in DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) diff --git a/util/Makefile.in b/util/Makefile.in index 99ac0a5ab..a6385a6bf 100644 --- a/util/Makefile.in +++ b/util/Makefile.in @@ -109,7 +109,7 @@ AR = ar CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ -DIST_COMMON = Makefile.am Makefile.in +DIST_COMMON = ChangeLog Makefile.am Makefile.in DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) diff --git a/util/iobuf.c b/util/iobuf.c index d429d4c1e..65efc0ef5 100644 --- a/util/iobuf.c +++ b/util/iobuf.c @@ -313,7 +313,7 @@ iobuf_close( IOBUF a ) size_t dummy_len; int rc=0; - for( ; a; a = a2 ) { + for( ; a && !rc ; a = a2 ) { a2 = a->chain; if( a->usage == 2 && (rc=iobuf_flush(a)) ) log_error("iobuf_flush failed on close: %s\n", g10_errstr(rc)); @@ -724,6 +724,26 @@ iobuf_readbyte(IOBUF a) int +iobuf_read(IOBUF a, byte *buf, unsigned buflen ) +{ + int c, n; + + for(n=0 ; n < buflen; n++, buf++ ) { + if( (c = iobuf_readbyte(a)) == -1 ) { + if( !n ) + return -1; /* eof */ + break; + } + else + *buf = c; + } + return n; +} + + + + +int iobuf_writebyte(IOBUF a, unsigned c) { if( a->d.len == a->d.size ) |