a couple of changes; but some parts are now broken
authorWerner Koch <wk@gnupg.org>
Wed, 11 Feb 1998 03:25:44 +0000 (03:25 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 11 Feb 1998 03:25:44 +0000 (03:25 +0000)
46 files changed:
ChangeLog
Makefile.in
NEWS
THANKS [new file with mode: 0644]
TODO
VERSION
cipher/Makefile.in
cipher/blowfish.c
cipher/elgamal.c
cipher/md5.c
cipher/rmd160.c
cipher/sha1.c
g10/Makefile.in
g10/g10.c
g10/g10maint.c
g10/kbnode.c
g10/keydb.h
g10/keygen.c
g10/mainproc.c
g10/packet.h
g10/parse-packet.c
g10/ringedit.c
g10/sig-check.c
g10/sign.c
g10/trustdb.c
include/errors.h
include/i18n.h
include/iobuf.h
include/mpi.h
mpi/Makefile.am
mpi/Makefile.in
mpi/config.links
mpi/i586/README [new file with mode: 0644]
mpi/i586/distfiles [new file with mode: 0644]
mpi/i586/mpih-add1.S [new file with mode: 0644]
mpi/i586/mpih-mul1.S [new file with mode: 0644]
mpi/i586/mpih-mul2.S [new file with mode: 0644]
mpi/i586/mpih-mul3.S [new file with mode: 0644]
mpi/i586/mpih-shift.S [new file with mode: 0644]
mpi/i586/mpih-sub1.S [new file with mode: 0644]
mpi/mpi-inv.c
mpi/mpi-mpow.c [new file with mode: 0644]
po/ChangeLog
tools/Makefile.in
util/Makefile.in
util/iobuf.c

index e69de29..1d25265 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -0,0 +1,5 @@
+Tue Feb 10 11:57:23 1998  Werner Koch  (wk@frodo)
+
+       * ddd/hhhh:
+
+
index 6097936..37e30e8 100644 (file)
@@ -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)
diff --git a/NEWS b/NEWS
index ef258c6..0a8ffa1 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -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
diff --git a/THANKS b/THANKS
new file mode 100644 (file)
index 0000000..4f53c92
--- /dev/null
+++ b/THANKS
@@ -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.
diff --git a/TODO b/TODO
index 5a8fc79..1b63c1e 100644 (file)
--- a/TODO
+++ b/TODO
@@ -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.
-
 
diff --git a/VERSION b/VERSION
index 7179039..ccd3d1a 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.2.3
+0.2.3x
index 9e4860f..e4ab5ed 100644 (file)
@@ -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)
index 81e33d0..8e3a493 100644 (file)
@@ -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;
index 5e6bd0c..13b8579 100644 (file)
@@ -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);
index c9f9a86..ef95c7e 100644 (file)
@@ -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 */
index 0b501d7..39f1c74 100644 (file)
@@ -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;
index 51029c4..a54ec6a 100644 (file)
 #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
index 6bcb29e..bae7c65 100644 (file)
@@ -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)
index 410aeaa..8036694 100644 (file)
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -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;
index 4352045..e8a4437 100644 (file)
@@ -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
 }
 
index 19e0870..3096c4d 100644 (file)
@@ -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;
     }
 }
index 818b643..ff0ecb5 100644 (file)
@@ -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 --*/
index d73573c..09d2dc2 100644 (file)
@@ -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;
index cae7ddd..1ef8a8b 100644 (file)
@@ -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;
index 8d3018d..d0bb3c4 100644 (file)
@@ -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 );
index c49b6f5..2e3cf21 100644 (file)
@@ -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
 }
 
 
index 61f915c..141d8cf 100644 (file)
@@ -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;
 }
 
 
index fcc2a69..cc13367 100644 (file)
@@ -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 ) {
index 883a8d4..a59598c 100644 (file)
@@ -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;
index d317a66..3f567e8 100644 (file)
@@ -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 );
index fcae69e..36aff5b 100644 (file)
@@ -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*/
index a75f3c4..d43c078 100644 (file)
 #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)
index e5ce81a..a57d7a9 100644 (file)
@@ -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 );
index 1354dda..87bb053 100644 (file)
@@ -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 );
index 1c32e13..2801a75 100644 (file)
@@ -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     \
index aae7160..bcbbc64 100644 (file)
@@ -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)
 
index 923e18b..cf370e0 100644 (file)
@@ -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 (file)
index 0000000..d73b082
--- /dev/null
@@ -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 (file)
index 0000000..951480f
--- /dev/null
@@ -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 (file)
index 0000000..e988328
--- /dev/null
@@ -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 (file)
index 0000000..c0bedec
--- /dev/null
@@ -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 (file)
index 0000000..6b56462
--- /dev/null
@@ -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 (file)
index 0000000..69b7f46
--- /dev/null
@@ -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 (file)
index 0000000..9f15638
--- /dev/null
@@ -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 (file)
index 0000000..1f5c0bf
--- /dev/null
@@ -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
+
index 28cde00..53ef356 100644 (file)
@@ -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 (file)
index 0000000..5ac3c63
--- /dev/null
@@ -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);
+}
+
index e69de29..1d25265 100644 (file)
@@ -0,0 +1,5 @@
+Tue Feb 10 11:57:23 1998  Werner Koch  (wk@frodo)
+
+       * ddd/hhhh:
+
+
index 0594ccd..add8db5 100644 (file)
@@ -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)
index 99ac0a5..a6385a6 100644 (file)
@@ -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)
index d429d4c..65efc0e 100644 (file)
@@ -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 )