import works
authorWerner Koch <wk@gnupg.org>
Tue, 17 Feb 1998 20:48:52 +0000 (20:48 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 17 Feb 1998 20:48:52 +0000 (20:48 +0000)
33 files changed:
README
g10/ChangeLog
g10/Makefile.am
g10/OPTIONS
g10/armor.c
g10/free-packet.c
g10/g10.c
g10/g10maint.c
g10/getkey.c
g10/import.c
g10/kbnode.c
g10/keydb.h
g10/keygen.c
g10/main.h
g10/mainproc.c
g10/options.h
g10/packet.h
g10/pubring.asc [new file with mode: 0644]
g10/pubring.g10 [deleted file]
g10/ringedit.c
g10/sign.c
g10/trustdb.c
mpi/m68k/distfiles
mpi/m68k/mc68020/distfiles
mpi/m68k/mc68020/mpih-mul1.S [new file with mode: 0644]
mpi/m68k/mc68020/mpih-mul2.S [new file with mode: 0644]
mpi/m68k/mc68020/mpih-mul3.S [new file with mode: 0644]
mpi/m68k/mpih-add1.S [new file with mode: 0644]
mpi/m68k/mpih-shift.S [new file with mode: 0644]
mpi/m68k/mpih-sub1.S [new file with mode: 0644]
mpi/mpi-inv.c
util/ChangeLog
util/memory.c

diff --git a/README b/README
index f5dc7a8..52e6e14 100644 (file)
--- a/README
+++ b/README
     8) Continue with step 4 if we did not find a prime in step 7.
     9) Find a generator for that prime.
 
+    You should make a revocation certificate in cases someone gets
+    knowledge of your secret key or you forgot your passphrase:
+
+       g10 --gen-revoke your_user_id
+
+    Run this command and store it away; output is always ASCII armored,
+    so that you can print it and (hopefully never) re-create it if
+    your electronic media fails.
+
 
     You can sign a key with this command:
 
     wether you want to sign this key.
 
     You may remove a signature at any time using the option "--edit-sig",
-    which asks for the sigs to remove.
+    which asks for the sigs to remove. Self-signatures are not removable.
+
+
 
 
     Sign
     Ditto, but sign the file with the user id "Suttner"
 
 
+    Keyring Management
+    ------------------
+    To export your complete keyring(s) do this:
+
+       g10 --export
+
+    To export only some user ids do this:
+
+       g10 --export userids
+
+    Use "-a" or "--armor" to create ASCII armored output.
+
+    Importing keys is done with the option, you guessed it, "--import":
+
+       g10 --import [filenames]
+
+    New keys are appended to the default keyring and already existing
+    keys are merged.  Keys without a self-signature are ignored.
+
+
     How to Specify a UserID
     -----------------------
     There are several ways to specify a userID, here are some examples:
index 4e1cf43..414b051 100644 (file)
@@ -1,3 +1,37 @@
+Tue Feb 17 21:24:17 1998  Werner Koch  (wk@isil.d.shuttle.de)
+
+       * armor.c : Add header lines "...ARMORED FILE .."
+       * dearmor.c (enarmor_file): New.
+       * g10maint.c (main): New option "--enarmor"
+
+Tue Feb 17 19:03:33 1998  Werner Koch  (wk@isil.d.shuttle.de)
+
+       * mainproc.c : Changed a lot, because the packets are now stored
+       a simple linlked list and not anymore in a complicatd tree structure.
+
+Tue Feb 17 10:14:48 1998  Werner Koch  (wk@isil.d.shuttle.de)
+
+       * free_packet.c (cmp_public_certs): New.
+       (cmp_user_ids): New.
+
+       * kbnode.c (clone_kbnode): New.
+       (release_kbnode): Add clone support.
+
+       * ringedit.c (find_keyblock_bypkc): New.
+
+       * sign.c (remove_keysigs): Self signatures are now skipped,
+       changed arguments and all callers.
+
+       * import.c : Add functionality.
+
+Tue Feb 17 09:31:40 1998  Werner Koch  (wk@isil.d.shuttle.de)
+
+       * options.h (homedir): New option.
+       * g10.c, g10maint.c, getkey.c, keygen.c, trustdb.c (opt.homedir): New.
+
+       * trustdb.c (init_trustdb): mkdir for hoem directory
+       (sign_private_data): Renamed "sig" to "g10.sig"
+
 Mon Feb 16 20:02:03 1998  Werner Koch  (wk@isil.d.shuttle.de)
 
        * kbnode.c (commit_kbnode): New.
index e200fcd..44cc3ae 100644 (file)
@@ -1,7 +1,7 @@
 ## Process this file with automake to produce Makefile.in
 
 INCLUDES = -I$(top_srcdir)/include
-EXTRA_DIST = OPTIONS  pubring.g10
+EXTRA_DIST = OPTIONS  pubring.asc
 needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a
 
 bin_PROGRAMS = g10 g10maint
index 37c6ec4..c4e6afd 100644 (file)
@@ -132,6 +132,9 @@ armor
 batch
 # batch mode: never ask
 
+no-batch
+# disables batch
+
 cache-all
 # hold everything in memory
 
@@ -152,6 +155,8 @@ detach-sign
 dry-run
 # don't make any changes
 
+homedir dirname
+# Set the name of the home directory which defaults to "~/.g10".
 
 keyring  filename
 # add this filename to the list of keyrings.
@@ -180,6 +185,10 @@ no-verbose
 options filename
 #  Ignored in option files.
 
+no-options
+# same as --options /dev/null. This option is detected
+# before an attempt to open an option file
+
 output filename
 # use filename for output
 
index 17dc444..03a393b 100644 (file)
@@ -87,12 +87,15 @@ static char *head_strings[] = {
     "BEGIN PGP PUBLIC KEY BLOCK",
     "BEGIN PGP SIGNATURE",
     "BEGIN PGP SIGNED MESSAGE",
+    "BEGIN PGP ARMORED FILE",
     NULL
 };
 static char *tail_strings[] = {
     "END PGP MESSAGE",
     "END PGP PUBLIC KEY BLOCK",
     "END PGP SIGNATURE",
+    "END dummy",
+    "END PGP ARMORED FILE",
     NULL
 };
 
@@ -248,7 +251,7 @@ static fhdr_state_t
 find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
                                        IOBUF a, size_t n, unsigned *r_empty)
 {
-    int c, i;
+    int c=0, i;
     const char *s;
     byte *p;
     size_t buflen;
index 949af10..f2467a7 100644 (file)
@@ -275,6 +275,37 @@ free_packet( PACKET *pkt )
  * Returns 0 if they match.
  */
 int
+cmp_public_certs( PKT_public_cert *a, PKT_public_cert *b )
+{
+    if( a->timestamp != b->timestamp )
+       return -1;
+    if( a->valid_days != b->valid_days )
+       return -1;
+    if( a->pubkey_algo != b->pubkey_algo )
+       return -1;
+
+    if( a->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
+       if( mpi_cmp( a->d.elg.p , b->d.elg.p ) )
+           return -1;
+       if( mpi_cmp( a->d.elg.g , b->d.elg.g ) )
+           return -1;
+       if( mpi_cmp( a->d.elg.y , b->d.elg.y ) )
+           return -1;
+    }
+    else if( a->pubkey_algo == PUBKEY_ALGO_RSA ) {
+       if( mpi_cmp( a->d.rsa.rsa_n , b->d.rsa.rsa_n ) )
+           return -1;
+       if( mpi_cmp( a->d.rsa.rsa_e , b->d.rsa.rsa_e ) )
+           return -1;
+    }
+
+    return 0;
+}
+
+/****************
+ * Returns 0 if they match.
+ */
+int
 cmp_public_secret_cert( PKT_public_cert *pkc, PKT_secret_cert *skc )
 {
     if( pkc->timestamp != skc->timestamp )
@@ -302,3 +333,15 @@ cmp_public_secret_cert( PKT_public_cert *pkc, PKT_secret_cert *skc )
     return 0;
 }
 
+int
+cmp_user_ids( PKT_user_id *a, PKT_user_id *b )
+{
+    int res;
+
+    res = a->len - b->len;
+    if( !res )
+       res = memcmp( a->name, b->name, a->len );
+    return res;
+}
+
+
index fae08fc..f9ae0fc 100644 (file)
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -109,7 +109,9 @@ static ARGPARSE_OPTS opts[] = {
     { 522, "no-greeting", 0, "\r" },
     { 523, "passphrase-fd",1, "\r" },
     { 541, "no-operation", 0, "\r" },      /* used by regression tests */
-
+    { 543, "no-options", 0, "\r" }, /* shortcut for --options /dev/null */
+    { 544, "homedir", 2, "\r" },   /* defaults to "~/.g10" */
+    { 545, "no-batch", 0, "\r" },
 
 {0} };
 
@@ -324,6 +326,7 @@ main( int argc, char **argv )
     opt.def_digest_algo = DIGEST_ALGO_RMD160;
     opt.completes_needed = 1;
     opt.marginals_needed = 3;
+    opt.homedir = "~/.g10";
 
     /* check wether we have a config file on the commandline */
     orig_argc = argc;
@@ -340,10 +343,14 @@ main( int argc, char **argv )
             */
            default_config = 0;
        }
+       else if( pargs.r_opt == 543 )
+           default_config = 0; /* --no-options */
+       else if( pargs.r_opt == 544 )
+           opt.homedir = pargs.r.ret_str;
     }
 
     if( default_config )
-       configname = make_filename("~/.g10", "options", NULL );
+       configname = make_filename(opt.homedir, "options", NULL );
 
     argc = orig_argc;
     argv = orig_argv;
@@ -357,7 +364,8 @@ main( int argc, char **argv )
        if( !configfp ) {
            if( default_config ) {
                if( parse_debug )
-               log_info(_("note: no default option file '%s'\n"), configname );
+                   log_info(_("note: no default option file '%s'\n"),
+                                                           configname );
            }
            else {
                log_error(_("option file '%s': %s\n"),
@@ -447,6 +455,9 @@ main( int argc, char **argv )
          case 540: secmem_set_flags( secmem_get_flags() | 1 ); break;
          case 541: set_cmd( &cmd, aNOP); break;
          case 542: set_cmd( &cmd, aGenRevoke); break;
+         case 543: break; /* no-options */
+         case 544: opt.homedir = pargs.r.ret_str; break;
+         case 545: opt.batch = 0; break;
          default : errors++; pargs.err = configfp? 1:2; break;
        }
     }
@@ -652,8 +663,11 @@ main( int argc, char **argv )
        break;
 
       case aImport:
-       if( !argc  )
-           wrong_args(_("nyi"));
+       if( !argc  ) {
+           rc = import_pubkeys( NULL );
+           if( rc )
+               log_error("import failed: %s\n", g10_errstr(rc) );
+       }
        for( ; argc; argc--, argv++ ) {
            rc = import_pubkeys( *argv );
            if( rc )
index 618acc8..c743bf9 100644 (file)
@@ -43,7 +43,7 @@
 
 enum cmd_values { aNull = 0,
     aPrimegen, aPrintMDs, aListPackets, aKMode, aKModeC,
-    aListTrustDB, aListTrustPath, aDeArmor,
+    aListTrustDB, aListTrustPath, aDeArmor, aEnArmor,
 aTest };
 
 
@@ -219,7 +219,12 @@ main( int argc, char **argv )
     { 535, "completes-needed", 1, N_("(default is 1)")},
     { 536, "marginals-needed", 1, N_("(default is 3)")},
     { 538, "trustdb-name", 2, "\r" },
-    { 540, "dearmor", 0, N_("De-Armor a file or stdin") },
+    { 540, "no-secmem-warning", 0, "\r" }, /* dummy */
+    { 543, "no-options", 0, "\r" }, /* shortcut for --options /dev/null */
+    { 544, "homedir", 2, "\r" },   /* defaults to "~/.g10" */
+    { 545, "no-batch", 0, "\r" },
+    { 546, "dearmor", 0, N_("De-Armor a file or stdin") },
+    { 547, "enarmor", 0, N_("En-Armor a file or stdin") },
 
     {0} };
     ARGPARSE_ARGS pargs;
@@ -245,6 +250,7 @@ main( int argc, char **argv )
 
     secmem_init( 0 ); /* disable use of secmem */
 
+    log_set_name("g10maint");
     i18n_init();
     opt.compress = -1; /* defaults to standard compress level */
     opt.def_cipher_algo = CIPHER_ALGO_BLOWFISH;
@@ -252,6 +258,7 @@ main( int argc, char **argv )
     opt.def_digest_algo = DIGEST_ALGO_RMD160;
     opt.completes_needed = 1;
     opt.marginals_needed = 3;
+    opt.homedir = "~/.g10";
 
     /* check wether we have a config file on the commandline */
     orig_argc = argc;
@@ -268,10 +275,14 @@ main( int argc, char **argv )
             */
            default_config = 0;
        }
+       else if( pargs.r_opt == 543 )
+           default_config = 0; /* --no-options */
+       else if( pargs.r_opt == 544 )
+           opt.homedir = pargs.r.ret_str;
     }
 
     if( default_config )
-       configname = make_filename("~/.g10", "options", NULL );
+       configname = make_filename(opt.homedir, "options", NULL );
 
     argc = orig_argc;
     argv = orig_argv;
@@ -349,7 +360,12 @@ main( int argc, char **argv )
          case 535: opt.completes_needed = pargs.r.ret_int; break;
          case 536: opt.marginals_needed = pargs.r.ret_int; break;
          case 538: trustdb_name = pargs.r.ret_str; break;
-         case 540: set_cmd( &cmd, aDeArmor); break;
+         case 540: break; /*dummy*/
+         case 543: break; /* no-options */
+         case 544: opt.homedir = pargs.r.ret_str; break;
+         case 545: opt.batch = 0; break;
+         case 546: set_cmd( &cmd, aDeArmor); break;
+         case 547: set_cmd( &cmd, aEnArmor); break;
          default : errors++; pargs.err = configfp? 1:2; break;
        }
     }
@@ -407,12 +423,12 @@ main( int argc, char **argv )
     }
 
     if( !sec_nrings || default_keyring ) { /* add default secret rings */
-       char *p = make_filename("~/.g10", "secring.g10", NULL );
+       char *p = make_filename(opt.homedir, "secring.g10", NULL );
        add_secret_keyring(p);
        m_free(p);
     }
     if( !nrings || default_keyring ) { /* add default ring */
-       char *p = make_filename("~/.g10", "pubring.g10", NULL );
+       char *p = make_filename(opt.homedir, "pubring.g10", NULL );
        add_keyring(p);
        m_free(p);
     }
@@ -435,6 +451,8 @@ main( int argc, char **argv )
     switch( cmd ) {
       case aPrimegen:
       case aPrintMDs:
+      case aDeArmor:
+      case aEnArmor:
        break;
       case aListTrustDB: rc = init_trustdb( argc? 1:0, trustdb_name ); break;
       default: rc = init_trustdb(1, trustdb_name ); break;
@@ -484,6 +502,14 @@ main( int argc, char **argv )
            log_error(_("dearmoring failed: %s\n"), g10_errstr(rc));
        break;
 
+      case aEnArmor:
+       if( argc > 1 )
+           wrong_args("--enarmor [file]");
+       rc = enarmor_file( argc? *argv: NULL );
+       if( rc )
+           log_error(_("enarmoring failed: %s\n"), g10_errstr(rc));
+       break;
+
 
       case aPrimegen:
        if( argc == 1 ) {
index 8f92f0a..e58b0f8 100644 (file)
@@ -89,7 +89,7 @@ add_keyring( const char *name )
        if( strchr(name, '/') )
            p = make_filename(name, NULL);
        else
-           p = make_filename("~/.g10", name, NULL);
+           p = make_filename(opt.homedir, name, NULL);
        sl = m_alloc( sizeof *sl + strlen(p) );
        strcpy(sl->d, p );
        m_free(p);
@@ -139,7 +139,7 @@ add_secret_keyring( const char *name )
        if( strchr(name, '/') )
            p = make_filename(name, NULL);
        else
-           p = make_filename("~/.g10", name, NULL);
+           p = make_filename(opt.homedir, name, NULL);
        sl = m_alloc( sizeof *sl + strlen(p) );
        strcpy(sl->d, p );
        m_free(p);
index ce2655b..43e6423 100644 (file)
@@ -41,6 +41,12 @@ static int import_one( const char *fname, KBNODE keyblock );
 static int chk_self_sigs( const char *fname, KBNODE keyblock,
                          PKT_public_cert *pkc, u32 *keyid );
 static int delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid );
+static int merge_blocks( const char *fname, KBNODE keyblock_orig,
+                      KBNODE keyblock, u32 *keyid, int *n_uids, int *n_sigs );
+static int append_uid( KBNODE keyblock, KBNODE node, int *n_sigs,
+                            const char *fname, u32 *keyid );
+static int merge_sigs( KBNODE dst, KBNODE src, int *n_sigs,
+                            const char *fname, u32 *keyid );
 
 
 /****************
@@ -131,12 +137,15 @@ read_block( IOBUF a, compress_filter_context_t *cfx,
     int rc;
     PACKET *pkt;
     KBNODE root = NULL;
-    int in_cert = 0;
+    int in_cert;
 
     if( *pending_pkt ) {
        root = new_kbnode( *pending_pkt );
        *pending_pkt = NULL;
+       in_cert = 1;
     }
+    else
+       in_cert = 0;
     pkt = m_alloc( sizeof *pkt );
     init_packet(pkt);
     while( (rc=parse_packet(a, pkt)) != -1 ) {
@@ -165,6 +174,7 @@ read_block( IOBUF a, compress_filter_context_t *cfx,
            init_packet(pkt);
            break;
 
+
          case PKT_PUBLIC_CERT:
          case PKT_SECRET_CERT:
            if( in_cert ) { /* store this packet */
@@ -174,11 +184,13 @@ read_block( IOBUF a, compress_filter_context_t *cfx,
            }
            in_cert = 1;
          default:
-           if( !root )
-               root = new_kbnode( pkt );
-           else
-               add_kbnode( root, new_kbnode( pkt ) );
-           pkt = m_alloc( sizeof *pkt );
+           if( in_cert ) {
+               if( !root )
+                   root = new_kbnode( pkt );
+               else
+                   add_kbnode( root, new_kbnode( pkt ) );
+               pkt = m_alloc( sizeof *pkt );
+           }
            init_packet(pkt);
            break;
        }
@@ -209,6 +221,7 @@ import_one( const char *fname, KBNODE keyblock )
     PKT_public_cert *pkc;
     PKT_public_cert *pkc_orig;
     KBNODE node, uidnode;
+    KBNODE keyblock_orig = NULL;
     KBPOS kbpos;
     u32 keyid[2];
     int rc = 0;
@@ -243,20 +256,21 @@ import_one( const char *fname, KBNODE keyblock )
     rc = chk_self_sigs( fname, keyblock , pkc, keyid );
     if( rc )
        return rc== -1? 0:rc;
+
     if( !delete_inv_parts( fname, keyblock, keyid ) ) {
-       log_info("%s: key %08lX, no valid user ids left over\n",
+       log_info("%s: key %08lX, no valid user ids\n",
                                                    fname, (ulong)keyid[1]);
        return 0;
     }
 
     /* do we have this key already in one of our pubrings ? */
-    pkc_orig = m_alloc( sizeof *pkc_orig );
+    pkc_orig = m_alloc_clear( sizeof *pkc_orig );
     rc = get_pubkey( pkc_orig, keyid );
     if( rc && rc != G10ERR_NO_PUBKEY ) {
        log_error("%s: key %08lX, public key not found: %s\n",
                                fname, (ulong)keyid[1], g10_errstr(rc));
     }
-    else if( rc ) { /* inset this key */
+    else if( rc ) { /* insert this key */
        /* get default resource */
        if( get_keyblock_handle( NULL, 0, &kbpos ) ) {
            log_error("no default public keyring\n");
@@ -273,31 +287,80 @@ import_one( const char *fname, KBNODE keyblock )
                             keyblock_resource_name(&kbpos), g10_errstr(rc) );
        unlock_keyblock( &kbpos );
        /* we are ready */
-       if( opt.verbose )
-           log_info("%s: key %08lX imported\n", fname, (ulong)keyid[1]);
+       log_info("%s: key %08lX imported\n", fname, (ulong)keyid[1]);
     }
-    else {
-       /* merge
-       * o Compare the key and the self-signatures of the new and the one in
-       *   our keyring.  If they are different something weird is going on;
-       *   ask what to do.
-       * o See wether we have only non-self-signature on one user id; if not
-       *   ask the user what to do.
-       * o compare the signatures: If we already have this signature, check
-       *   that they compare okay; if not, issue a warning and ask the user.
-       *   (consider to look at the timestamp and use the newest?)
-       * o Simply add the signature.  Can't verify here because we may not have
-       *   the signatures public key yet; verification is done when putting it
-       *   into the trustdb, which is done automagically as soon as this pubkey
-       *   is used.
-       */
-       log_error("nyi\n");
+    else { /* merge */
+       int n_uids, n_sigs;
+
+       /* Compare the original against the new key; just to be sure nothing
+        * weird is going on */
+       if( cmp_public_certs( pkc_orig, pkc ) ) {
+           log_error("%s: key %08lX, doesn't match our copy\n",
+                                                   fname, (ulong)keyid[1]);
+           rc = G10ERR_GENERAL;
+           goto leave;
+       }
+
+       /* See wether we have only non-self-signature on one user id; if not
+        * ask the user what to do. <--- fixme */
+
+       /* now read the original keyblock */
+       rc = find_keyblock_bypkc( &kbpos, pkc_orig );
+       if( rc ) {
+           log_error("%s: key %08lX, can't locate original keyblock: %s\n",
+                                    fname, (ulong)keyid[1], g10_errstr(rc));
+           goto leave;
+       }
+       rc = read_keyblock( &kbpos, &keyblock_orig );
+       if( rc ) {
+           log_error("%s: key %08lX, can't read original keyblock: %s\n",
+                                    fname, (ulong)keyid[1], g10_errstr(rc));
+           goto leave;
+       }
+       /* and try to merge the block */
+       clear_kbnode_flags( keyblock_orig );
+       clear_kbnode_flags( keyblock );
+       n_uids = n_sigs = 0;
+       rc = merge_blocks( fname, keyblock_orig, keyblock,
+                               keyid, &n_uids, &n_sigs );
+       if( rc )
+           goto leave;
+       if( n_uids || n_sigs ) { /* keyblock_orig has been updated; write */
+           if( opt.verbose > 1 )
+               log_info("%s: writing to '%s'\n",
+                                   fname, keyblock_resource_name(&kbpos) );
+           if( (rc=lock_keyblock( &kbpos )) )
+               log_error("can't lock public keyring '%s': %s\n",
+                                keyblock_resource_name(&kbpos), g10_errstr(rc) );
+           else if( (rc=insert_keyblock( &kbpos, keyblock )) )
+               log_error("%s: can't write to '%s': %s\n", fname,
+                                keyblock_resource_name(&kbpos), g10_errstr(rc) );
+           unlock_keyblock( &kbpos );
+           /* we are ready */
+           if( n_uids == 1 )
+               log_info("%s: key %08lX, 1 new user-id\n",
+                                        fname, (ulong)keyid[1]);
+           else if( n_uids )
+               log_info("%s: key %08lX, %d new user-ids\n",
+                                        fname, (ulong)keyid[1], n_uids );
+           if( n_sigs == 1 )
+               log_info("%s: key %08lX, 1 new signature\n",
+                                        fname, (ulong)keyid[1]);
+           else if( n_sigs )
+               log_info("%s: key %08lX, %d new signatures\n",
+                                        fname, (ulong)keyid[1], n_sigs );
+       }
+       else
+           log_info("%s: key %08lX, not changed\n", fname, (ulong)keyid[1] );
     }
 
+  leave:
+    release_kbnode( keyblock_orig );
     free_public_cert( pkc_orig );
     return rc;
 }
 
+
 /****************
  * loop over the keyblock an check all self signatures.
  * Mark all user-ids with a self-signature by setting flag bit 0.
@@ -335,7 +398,10 @@ chk_self_sigs( const char *fname, KBNODE keyblock,
 }
 
 /****************
- * delete all parts which are invalid.
+ * delete all parts which are invalidand those signatures whos
+ * public key algorithm is not availabe in this implemenation;
+ * but consider RSA as valid, because parse/build_packets knows
+ * about it.
  * returns: true if at least one valid user-id is left over.
  */
 static int
@@ -347,11 +413,13 @@ delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid )
     for(node=keyblock->next; node; node = node->next ) {
        if( node->pkt->pkttype == PKT_USER_ID ) {
            if( (node->flag & 2) || !(node->flag & 1) ) {
-               log_info("%s: key %08lX, removed userid '",
+               if( opt.verbose ) {
+                   log_info("%s: key %08lX, removed userid '",
                                                  fname, (ulong)keyid[1]);
-               print_string( stderr, node->pkt->pkt.user_id->name,
+                   print_string( stderr, node->pkt->pkt.user_id->name,
                                      node->pkt->pkt.user_id->len );
-               fputs("'\n", stderr );
+                   fputs("'\n", stderr );
+               }
                delete_kbnode( node ); /* the user-id */
                /* and all following packets up to the next user-id */
                while( node->next && node->next->pkt->pkttype != PKT_USER_ID ){
@@ -362,10 +430,169 @@ delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid )
            else
                nvalid++;
        }
+       else if( node->pkt->pkttype == PKT_SIGNATURE
+                && check_pubkey_algo( node->pkt->pkt.signature->pubkey_algo)
+                && node->pkt->pkt.signature->pubkey_algo != PUBKEY_ALGO_RSA )
+           delete_kbnode( node ); /* build_packet() can't handle this */
     }
 
-    /* note: because keyblock is the public key, ist is never marked
-     * for deletion and so the keyblock cannot chnage */
+    /* note: because keyblock is the public key, it is never marked
+     * for deletion and so keyblock cannot change */
     commit_kbnode( &keyblock );
     return nvalid;
 }
+
+
+/****************
+ * compare and merge the blocks
+ *
+ * o compare the signatures: If we already have this signature, check
+ *   that they compare okay; if not, issue a warning and ask the user.
+ *   FIXME: add the check, that we don` have duplicate signatures and the
+ *   warning in cases that the old/new signatures don't match.
+ * o Simply add the signature. Can't verify here because we may not have
+ *   the signatures public key yet; verification is done when putting it
+ *   into the trustdb, which is done automagically as soon as this pubkey
+ *   is used.
+ * Note: We indicate newly inserted packets with flag bit 0
+ */
+static int
+merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock,
+                                  u32 *keyid, int *n_uids, int *n_sigs )
+{
+    KBNODE node_orig, node;
+    int rc;
+
+    /* first, try to merge new ones in */
+    for(node_orig=keyblock_orig->next; node_orig; node_orig=node_orig->next ) {
+       if( !(node_orig->flag & 1) && node_orig->pkt->pkttype == PKT_USER_ID) {
+           /* find the user id in the imported keyblock */
+           for(node=keyblock->next; node; node=node->next )
+               if( !(node->flag & 1)
+                   && node->pkt->pkttype == PKT_USER_ID
+                   && !cmp_user_ids( node_orig->pkt->pkt.user_id,
+                                         node->pkt->pkt.user_id ) )
+                   break;
+           if( node ) { /* found: merge */
+               rc = merge_sigs( node_orig, node, n_sigs, fname, keyid );
+               if( rc )
+                   return rc;
+           }
+       }
+    }
+
+    /* second, add new user-ids */
+    for(node=keyblock->next; node; node=node->next ) {
+       if( !(node->flag & 1) && node->pkt->pkttype == PKT_USER_ID) {
+           /* do we have this in the original keyblock */
+           for(node_orig=keyblock_orig->next; node_orig;
+                                               node_orig=node_orig->next )
+               if( !(node_orig->flag & 1)
+                   && node_orig->pkt->pkttype == PKT_USER_ID
+                   && cmp_user_ids( node_orig->pkt->pkt.user_id,
+                                    node->pkt->pkt.user_id ) )
+                   break;
+           if( !node ) { /* this is a new user id: append */
+               rc = append_uid( keyblock_orig, node, n_sigs, fname, keyid);
+               if( rc )
+                   return rc;
+               ++*n_uids;
+           }
+       }
+    }
+
+    return 0;
+}
+
+
+/****************
+ * append the userid starting with NODE and all signatures to KEYBLOCK.
+ * Mark all new and copied packets by setting flag bit 0.
+ */
+static int
+append_uid( KBNODE keyblock, KBNODE node, int *n_sigs,
+                                         const char *fname, u32 *keyid )
+{
+    KBNODE n;
+
+    assert(node->pkt->pkttype == PKT_USER_ID );
+    /* at lease a self signature comes next to the user-id */
+    if( node->next->pkt->pkttype == PKT_USER_ID ) {
+       log_error("%s: key %08lX, our copy has no self-signature\n",
+                                                 fname, (ulong)keyid[1]);
+       return G10ERR_GENERAL;
+    }
+
+    for( ;node && node->pkt->pkttype != PKT_USER_ID; node = node->next ) {
+       /* we add a clone to the original keyblock, because this
+        * one is released first */
+       n = clone_kbnode(node);
+       add_kbnode( keyblock, n );
+       node->flag |= 1;
+       n->flag |= 1;
+       if( n->pkt->pkttype == PKT_SIGNATURE )
+           ++*n_sigs;
+    }
+
+    return 0;
+}
+
+
+/****************
+ * Merge the sigs from SRC onto DST. SRC and DST are both a PKT_USER_ID.
+ * (how should we handle comment packets here?)
+ */
+static int
+merge_sigs( KBNODE dst, KBNODE src, int *n_sigs,
+                                   const char *fname, u32 *keyid )
+{
+    KBNODE n, n2;
+    int found=0;
+
+    assert(dst->pkt->pkttype == PKT_USER_ID );
+    assert(src->pkt->pkttype == PKT_USER_ID );
+    /* at least a self signature comes next to the user-ids */
+    assert(src->next->pkt->pkttype != PKT_USER_ID );
+    if( dst->next->pkt->pkttype == PKT_USER_ID ) {
+       log_error("%s: key %08lX, our copy has no self-signature\n",
+                                                 fname, (ulong)keyid[1]);
+       return 0;
+    }
+
+
+    for(n=src->next; n && n->pkt->pkttype != PKT_USER_ID; n = n->next ) {
+       if( n->pkt->pkttype != PKT_SIGNATURE )
+           continue;
+       found = 0;
+       for(n2=dst->next; n2 && n2->pkt->pkttype != PKT_USER_ID; n2 = n2->next)
+           if( n2->pkt->pkttype == PKT_SIGNATURE
+               && n->pkt->pkt.signature->keyid[0]
+                  == n2->pkt->pkt.signature->keyid[0]
+               && n->pkt->pkt.signature->keyid[1]
+                  == n2->pkt->pkt.signature->keyid[1] ) {
+           found++;
+           break;
+       }
+
+       if( found ) { /* we already have this signature */
+           /* Hmmm: should we compare the timestamp etc?
+            * but then we have first to see wether this signature is valid
+            * - or - simply add it in such a case and let trustdb logic
+            * decide wether to remove the old one
+            */
+           continue;
+       }
+
+       /* This signature is new, append N to DST it.
+        * We add a clone to the original keyblock, because this
+        * one is released first */
+       n2 = clone_kbnode(n);
+       insert_kbnode( dst, n2, PKT_USER_ID );
+       n2->flag |= 1;
+       n->flag |= 1;
+       ++*n_sigs;
+    }
+
+    return 0;
+}
+
index c28748b..3137e61 100644 (file)
@@ -37,7 +37,19 @@ new_kbnode( PACKET *pkt )
     n->next = NULL;
     n->pkt = pkt;
     n->flag = 0;
-    n->private_flag=0; /* kludge to delete a node */
+    n->private_flag=0;
+    return n;
+}
+
+
+KBNODE
+clone_kbnode( KBNODE node )
+{
+    KBNODE n = m_alloc( sizeof *n );
+    n->next = NULL;
+    n->pkt = node->pkt;
+    n->private_flag |= 2; /* mark cloned */
+    n->flag = 0;
     return n;
 }
 
@@ -49,7 +61,8 @@ release_kbnode( KBNODE n )
 
     while( n ) {
        n2 = n->next;
-       free_packet( n->pkt );
+       if( !(n->private_flag & 2) )
+           free_packet( n->pkt );
        m_free( n );
        n = n2;
     }
@@ -66,6 +79,7 @@ delete_kbnode( KBNODE node )
     node->private_flag |= 1;
 }
 
+
 /****************
  * Append NODE to ROOT, ROOT must exist!
  */
@@ -206,19 +220,67 @@ clear_kbnode_flags( KBNODE n )
 int
 commit_kbnode( KBNODE *root )
 {
-    KBNODE n, n2;
+    KBNODE n, nl;
     int changed = 0;
 
-    for(n=*root; n; n = n2 ) {
-       n2 = n->next;
+    for( n = *root, nl=NULL; n; n = nl->next ) {
        if( (n->private_flag & 1) ) {
            if( n == *root )
-               *root = n2;
-           free_packet( n->pkt );
+               *root = nl = n->next;
+           else
+               nl->next = n->next;
+           if( !(n->private_flag & 2) )
+               free_packet( n->pkt );
            m_free( n );
            changed = 1;
        }
+       else
+           nl = n;
     }
     return changed;
 }
 
+
+void
+dump_kbnode( KBNODE node )
+{
+    for(; node; node = node->next ) {
+       const char *s;
+       switch( node->pkt->pkttype ) {
+         case 0:               s="empty"; break;
+         case PKT_PUBLIC_CERT: s="public-key"; break;
+         case PKT_SECRET_CERT: s="secret-key"; break;
+         case PKT_SECKEY_SUBCERT:  s= "secret-subkey"; break;
+         case PKT_PUBKEY_ENC:  s="public-enc"; break;
+         case PKT_SIGNATURE:   s="signature"; break;
+         case PKT_ONEPASS_SIG: s="onepass-sig"; break;
+         case PKT_USER_ID:     s="user-id"; break;
+         case PKT_PUBKEY_SUBCERT: s="public-subkey"; break;
+         case PKT_COMMENT:     s="comment"; break;
+         case PKT_RING_TRUST:  s="trust"; break;
+         case PKT_PLAINTEXT:   s="plaintext"; break;
+         case PKT_COMPRESSED:  s="compressed"; break;
+         case PKT_ENCRYPTED:   s="encrypted"; break;
+         default:              s="unknown"; break;
+       }
+       fprintf(stderr, "node %p %02x/%02x type=%s",
+               node, node->flag, node->private_flag, s);
+       if( node->pkt->pkttype == PKT_USER_ID ) {
+           fputs("  \"", stderr);
+           print_string( stderr, node->pkt->pkt.user_id->name,
+                                 node->pkt->pkt.user_id->len );
+           fputs("\"\n", stderr);
+       }
+       else if( node->pkt->pkttype == PKT_SIGNATURE ) {
+           fprintf(stderr, "  keyid=%08lX\n",
+                  (ulong)node->pkt->pkt.signature->keyid[1] );
+       }
+       else if( node->pkt->pkttype == PKT_PUBLIC_CERT ) {
+           fprintf(stderr, "  keyid=%08lX\n", (ulong)
+                 keyid_from_pkc( node->pkt->pkt.public_cert, NULL ));
+       }
+       else
+           fputs("\n", stderr);
+    }
+}
+
index 643632a..eff603a 100644 (file)
@@ -127,6 +127,7 @@ byte *fingerprint_from_pkc( PKT_public_cert *pkc, size_t *ret_len );
 
 /*-- kbnode.c --*/
 KBNODE new_kbnode( PACKET *pkt );
+KBNODE clone_kbnode( KBNODE node );
 void release_kbnode( KBNODE n );
 void delete_kbnode( KBNODE node );
 void add_kbnode( KBNODE root, KBNODE node );
@@ -144,6 +145,7 @@ const char *keyblock_resource_name( KBPOS *kbpos );
 int get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos );
 int find_keyblock( PUBKEY_FIND_INFO info, KBPOS *kbpos );
 int find_keyblock_byname( KBPOS *kbpos, const char *username );
+int find_keyblock_bypkc( KBPOS *kbpos, PKT_public_cert *pkc );
 int find_secret_keyblock_byname( KBPOS *kbpos, const char *username );
 int lock_keyblock( KBPOS *kbpos );
 void unlock_keyblock( KBPOS *kbpos );
index 89fd852..f0cbda3 100644 (file)
@@ -526,8 +526,8 @@ generate_keypair()
 
 
     /* now check wether we a are allowed to write to the keyrings */
-    pub_fname = make_filename("~/.g10", "pubring.g10", NULL );
-    sec_fname = make_filename("~/.g10", "secring.g10", NULL );
+    pub_fname = make_filename(opt.homedir, "pubring.g10", NULL );
+    sec_fname = make_filename(opt.homedir, "secring.g10", NULL );
     if( opt.verbose ) {
        tty_printf(_("writing public certificate to '%s'\n"), pub_fname );
        tty_printf(_("writing secret certificate to '%s'\n"), sec_fname );
index 8761a1c..2990ef8 100644 (file)
@@ -91,6 +91,7 @@ int import_pubkeys( const char *filename );
 int export_pubkeys( STRLIST users );
 /* dearmor.c --*/
 int dearmor_file( const char *fname );
+int enarmor_file( const char *fname );
 
 /*-- revoke.c --*/
 int gen_revoke( const char *uname );
index 7e19f12..f2b50ac 100644 (file)
@@ -47,7 +47,7 @@ typedef struct {
     md_filter_context_t mfx;
     DEK *dek;
     int last_was_pubkey_enc;
-    KBNODE cert;     /* the current certificate / or signature */
+    KBNODE list;   /* the current list of packets */
     int have_data;
     IOBUF iobuf;    /* used to get the filename etc. */
 } *CTX;
@@ -59,13 +59,13 @@ static void proc_tree( CTX c, KBNODE node );
 
 
 static void
-release_cert( CTX c )
+release_list( CTX c )
 {
-    if( !c->cert )
+    if( !c->list )
        return;
-    proc_tree(c, c->cert );
-    release_kbnode( c->cert );
-    c->cert = NULL;
+    proc_tree(c, c->list );
+    release_kbnode( c->list );
+    c->list = NULL;
 }
 
 
@@ -74,17 +74,15 @@ add_onepass_sig( CTX c, PACKET *pkt )
 {
     KBNODE node;
 
-    if( c->cert ) { /* add another packet */
-       if( c->cert->pkt->pkttype != PKT_ONEPASS_SIG ) {
+    if( c->list ) { /* add another packet */
+       if( c->list->pkt->pkttype != PKT_ONEPASS_SIG ) {
           log_error("add_onepass_sig: another packet is in the way\n");
-          release_cert( c );
+          release_list( c );
        }
-       node = new_kbnode( pkt );
-       node->next = c->cert;
-       c->cert = node;
+       add_kbnode( c->list, new_kbnode( pkt ));
     }
     else /* insert the first one */
-       c->cert = node = new_kbnode( pkt );
+       c->list = node = new_kbnode( pkt );
 
     return 1;
 }
@@ -93,16 +91,16 @@ add_onepass_sig( CTX c, PACKET *pkt )
 static int
 add_public_cert( CTX c, PACKET *pkt )
 {
-    release_cert( c );
-    c->cert = new_kbnode( pkt );
+    release_list( c );
+    c->list = new_kbnode( pkt );
     return 1;
 }
 
 static int
 add_secret_cert( CTX c, PACKET *pkt )
 {
-    release_cert( c );
-    c->cert = new_kbnode( pkt );
+    release_list( c );
+    c->list = new_kbnode( pkt );
     return 1;
 }
 
@@ -110,24 +108,11 @@ add_secret_cert( CTX c, PACKET *pkt )
 static int
 add_user_id( CTX c, PACKET *pkt )
 {
-    KBNODE node, n1;
-
-    if( !c->cert ) {
+    if( !c->list ) {
        log_error("orphaned user id\n" );
        return 0;
     }
-    /* goto the last certificate */
-    for(n1=c->cert; n1->next; n1 = n1->next )
-       ;
-    assert( n1->pkt );
-    if( n1->pkt->pkttype != PKT_PUBLIC_CERT
-       && n1->pkt->pkttype != PKT_SECRET_CERT ) {
-       log_error("invalid parent type %d for userid\n", n1->pkt->pkttype );
-       return 0;
-    }
-    /* add a new user id node at the end */
-    node = new_kbnode( pkt );
-    add_kbnode( n1, node );
+    add_kbnode( c->list, new_kbnode( pkt ) );
     return 1;
 }
 
@@ -137,7 +122,7 @@ add_signature( CTX c, PACKET *pkt )
 {
     KBNODE node;
 
-    if( pkt->pkttype == PKT_SIGNATURE && !c->cert ) {
+    if( pkt->pkttype == PKT_SIGNATURE && !c->list ) {
        /* 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
@@ -145,23 +130,17 @@ add_signature( CTX c, PACKET *pkt )
         * that it is not possible to make a signature from data read
         * from stdin.  (Anyway, G10 is able to read these stuff) */
        node = new_kbnode( pkt );
-       c->cert = node;
+       c->list = node;
        return 1;
     }
-    else if( !c->cert )
+    else if( !c->list )
        return 0; /* oops (invalid packet sequence)*/
-    else if( !c->cert->pkt )
+    else if( !c->list->pkt )
        BUG();  /* so nicht */
-    else if( c->cert->pkt->pkttype == PKT_ONEPASS_SIG ) {
-       /* The root is a onepass signature: we are signing data */
-       node = new_kbnode( pkt );
-       add_kbnode( c->cert, node );
-       return 1;
-    }
 
     /* add a new signature node id at the end */
     node = new_kbnode( pkt );
-    add_kbnode( c->cert, node );
+    add_kbnode( c->list, node );
     return 1;
 }
 
@@ -304,12 +283,12 @@ do_check_sig( CTX c, KBNODE node )
        md = md_copy( c->mfx.md );
     }
     else if( (sig->sig_class&~3) == 0x10 ) { /* classes 0x10 .. 0x13 */
-       if( c->cert->pkt->pkttype == PKT_PUBLIC_CERT ) {
-           KBNODE n1 = find_prev_kbnode( c->cert, node, PKT_USER_ID );
+       if( c->list->pkt->pkttype == PKT_PUBLIC_CERT ) {
+           KBNODE n1 = find_prev_kbnode( c->list, 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 );
+               if( c->list->pkt->pkt.public_cert->mfx.md )
+                   md = md_copy( c->list->pkt->pkt.public_cert->mfx.md );
                else
                    BUG();
                md_write( md, n1->pkt->pkt.user_id->name, n1->pkt->pkt.user_id->len);
@@ -394,15 +373,24 @@ list_node( CTX c, KBNODE node )
                                      (ulong)keyid_from_pkc( pkc, NULL ),
                                      datestr_from_pkc( pkc )     );
        /* 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;
+       for( node = node->next; node; node = node->next ) {
+           if( node->pkt->pkttype == PKT_USER_ID ) {
+               KBNODE n;
+
+               if( any )
+                   printf( "%*s", 31, "" );
+               print_userid( node->pkt );
+               putchar('\n');
+               if( opt.fingerprint && !any )
+                   print_fingerprint( pkc, NULL );
+               for( n=node->next; n; n = n->next ) {
+                   if( n->pkt->pkttype == PKT_USER_ID )
+                       break;
+                   if( n->pkt->pkttype == PKT_SIGNATURE )
+                       list_node(c,  n );
+               }
+               any=1;
+           }
        }
        if( !any )
            printf("ERROR: no user id!\n");
@@ -425,14 +413,9 @@ list_node( CTX c, KBNODE node )
        if( !any )
            printf("ERROR: no user id!\n");
     }
-    else if( node->pkt->pkttype == PKT_USER_ID ) {
-       /* list everything under this user id */
-       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;
-       int rc2;
+       int rc2=0;
        size_t n;
        char *p;
        int sigrc = ' ';
@@ -527,7 +510,7 @@ proc_packets( IOBUF a )
            free_packet(pkt);
     }
 
-    release_cert( c );
+    release_list( c );
     m_free(c->dek);
     free_packet( pkt );
     m_free( pkt );
index 89388f1..48c6bee 100644 (file)
@@ -42,7 +42,7 @@ struct {
     int no_comment;
     int marginals_needed;
     int completes_needed;
-    int reserved12;
+    const char *homedir;
     int reserved13;
     int reserved14;
     int reserved15;
index d0bb3c4..98015a3 100644 (file)
@@ -243,7 +243,9 @@ void free_comment( PKT_comment *rem );
 void free_packet( PACKET *pkt );
 PKT_public_cert *copy_public_cert( PKT_public_cert *d, PKT_public_cert *s );
 PKT_secret_cert *copy_secret_cert( PKT_secret_cert *d, PKT_secret_cert *s );
+int cmp_public_certs( PKT_public_cert *a, PKT_public_cert *b );
 int cmp_public_secret_cert( PKT_public_cert *pkc, PKT_secret_cert *skc );
+int cmp_user_ids( PKT_user_id *a, PKT_user_id *b );
 
 
 /*-- sig-check.c --*/
diff --git a/g10/pubring.asc b/g10/pubring.asc
new file mode 100644 (file)
index 0000000..436d1b5
--- /dev/null
@@ -0,0 +1,38 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: G10 v0.2.6a (Linux)
+Comment: This is an alpha version!
+
+owJ4nAHfBiD5mQFXAzTfJWgAABAFINbugE0d8vCiHfqvhnoptnqKVW0wf+wbDEgKR7puSi4NK0Og
+tq0NGF9drJozFMFQcBQ3JZwfFtzhn1uxQZIgAn3FbA+eFM0yIzoPBg6ZBwghyXAjRn53m2kKadtj
+Lw/MmvsSejhW9cAuGgQ+l3AnqGGr/FVf8UOYjONe/tQSkzBatwyDqlqo4aR53jtXSHyCs3HIBkb2
+Z9pJ7QgDRbpHTkyZ+V/nAAMFBSCtiXNEQmGdslpqMUgwjG2YS0r+kkLnHyBnYEidgT1DlveJ2Uam
+KXBzE03t8eP4BCHazC6YYtlLK0u73bzE93qlcqzmWqD29X/s3Ph0cfGNyftzIVyMq/ltzvA0WuWo
++DMVkiLfqywfkmWY1jPesyHXZ+BzFz55Hj7JQdrJbj4Z8OvSFN8YeJ1c4bxdyUebswyH75mbSTc+
+gXvmKKVoEHLhduKXqLQiV2VybmVyIEtvY2ggPHdrQGlzaWwuZC5zaHV0dGxlLmRlPokBXwMFEzTf
+JWgDbxG4/z6qCxADG0kFHjyJ/JQso57RBJhyP/C85qoEfs26dLClZQNmuy1kTt7Ua4Jrgi2T0mh/
++psyo90uCatdoQ4/BCPkEAQiTuttyoqCBejL9VI9NFw9drbMrv9YCJDrGJ60Cz1J4cZsMrQdmv+k
+H3odr0pHJSyeoWVh6uWWCdcf56tPhOvfn704pAMekiFyYYCRoEquYNBNYqbPGdyPa1wxqChoJ0ER
+fJQr1zpwz9aiBR9gheP48OUeNLqcDMRt+HIkerRLbS4Er7xFA1OzOPQ5GaYv1kIimeTibqzzJqg6
+KXT2IWmMaO/mOHcAhUX2HNwEPvQI7OhZXl2Fba0vcWeIz0iLY+72jUTdZuN1naHyLdsj4Zhz6Iuz
+QorfRlYSqa05HSAgVeZXY2UAbSWNAL3tMwZl1NB0yU3ClHk16yaJaeCOL6/tWMUBBPQbqu3Q5hrr
+yYFA8YjXAwUQNN8mPOETl2Ph2BJ1EAM3QwL9FC95f+80m1FzlMYUJYpqVPLOF7D2tP9/BzX1bskI
+Z0HRyVNFgDgZLhJ3IumtFwo/Pas5lg9VTQzki8fI47nlHUFFi5p6w0fBQKj8cObx3wmYfomCbjvj
+dFA6RIwq6jxlAv4zOktjAyFzGOEwAibaVFC4yerQYSsZOLTTadhKWaPcPK4k0ueuT7afyEde9u8q
++9Z4g+21RkYRy3K7Kav29Mdkum66VWfEHXcV/cKpUJKfSOUsTBuvT6H59ldipKjGA5iYzwM03yX9
+AAAQAwDrovWGUv7oGFqpZv7U4+I1RbynmO/aVPkv+PAuww8qreqEAeNSjrn8IbqOz9sTBxt6vE8V
+QAQPL0KCY6vDxNluoDsc0h020AxGomJ/u7fVNBpaeyMVmmYdwuJBm+5l/18AAwUDAL5RBdBDaMxQ
+4KvCKf1LzbSjYUa/xYe8KD9rVAQn8gN6BHZZVUTQnvysQvu3RUmTahWMnLPGIN8xlqnUNYTKrDid
+9QJftOjyMu8I0eBwQ55uURk8eOjOtBw6zrDDz3uydLQYd2VybmVyIDxkZDlqbkBhbXNhdC5vcmc+
+iNcDBRM03yX94ROXY+HYEnUQA/WdAwCPzC6dmLB4Gojgq9kgdi7gjNWgkSiMh1lNOa4zYmXrPmLr
+Pak5SS1UlgxqQ7bWAONGz3GPH+86krj43EbWbtTP5f6uyNUhVDo3rfG2MVB+EpU6DX9mCosbSHa/
+UJw62ykDAJjbBaX3K7eGv83Zx36KeeD8adwU6a11NbpJi84pVJOr3TQ7pJAL3A8odXO6PrBZn8t7
+7wvf3aVMSW9NKZ7sta/BJHTwm/7nr9TjI5pwcmD0cOuX2IZjXi/6o65a/erF6okBXwMFEDTfJl4D
+bxG4/z6qCxAD89QFHjBcJGk53igKPrMfpdfO8m6zCWAWSEyE/F/H1TTHr6CWo0H0Z7P7LIMMj/AH
+u95plOX+ajCaEUofoAaNM1pJMB7DLpkZR1j+Qy64IpnFRVGP90Vnqmbw7wUufONWsLf6iKx76ZkS
+ZS5Gg/KTbLle6/6vFfHjI1Mu85hmCyEZsTs6AHL3rROuJRUt951TeoOKHUSMo/ZDQfya+BlmbUbj
+NaEp0qr2BR4ypoz5jQSiQPUFN3I0RLRzR6bS+a1pUVucNMXQuu5GsvJpQW47DznFDDteZcpf+Qai
+KKcMfpUtbWOIIlWhMAtIAodBJxCqrgGWbVGEkGtcrK7IW8NUDfpe/+KLcFzvx2XPo8+RHWrTlgf1
+RhEXdNx2up7gbuiHf+CD8kABzkINfmdYizmD1/JE8+DO8gCMopcY2hYmStG4E2lUCq79qCCBeORg
+5AyKSNo=
+=Cg4U
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/g10/pubring.g10 b/g10/pubring.g10
deleted file mode 100644 (file)
index f458371..0000000
Binary files a/g10/pubring.g10 and /dev/null differ
index 6d3fc14..95f0ef6 100644 (file)
@@ -176,6 +176,7 @@ find_keyblock( PUBKEY_FIND_INFO info, KBPOS *kbpos )
            rc = keyring_search2( info, kbpos, resource_table[i].fname );
            if( !rc ) {
                kbpos->resno = i;
+               kbpos->fp = NULL;
                return 0;
            }
            if( rc != -1 ) {
@@ -213,6 +214,7 @@ search( PACKET *pkt, KBPOS *kbpos, int secret )
            rc = keyring_search( pkt, kbpos, resource_table[i].iobuf );
            if( !rc ) {
                kbpos->resno = i;
+               kbpos->fp = NULL;
                return 0;
            }
            if( rc != -1 ) {
@@ -251,6 +253,25 @@ find_keyblock_byname( KBPOS *kbpos, const char *username )
     return rc;
 }
 
+
+/****************
+ * Combined function to search for a key and get the position
+ * of the keyblock.
+ */
+int
+find_keyblock_bypkc( KBPOS *kbpos, PKT_public_cert *pkc )
+{
+    PACKET pkt;
+    int rc;
+
+    init_packet( &pkt );
+    pkt.pkttype = PKT_PUBLIC_CERT;
+    pkt.pkt.public_cert = pkc;
+    rc = search( &pkt, kbpos, 0 );
+    return rc;
+}
+
+
 /****************
  * Combined function to search for a username and get the position
  * of the keyblock. This function does not unprotect the secret key.
@@ -277,6 +298,7 @@ find_secret_keyblock_byname( KBPOS *kbpos, const char *username )
 }
 
 
+
 /****************
  * Lock the keyblock; wait until it's available
  * This function may change the internal data in kbpos, in cases
@@ -461,7 +483,7 @@ keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf )
     save_mode = set_packet_list_mode(0);
 
     if( iobuf_seek( iobuf, 0 ) ) {
-       log_error("can't rewind keyring file: %s\n", g10_errstr(rc));
+       log_error("can't rewind keyring file\n");
        rc = G10ERR_KEYRING_OPEN;
        goto leave;
     }
@@ -595,7 +617,7 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root )
     }
 
     if( iobuf_seek( a, kbpos->offset ) ) {
-       log_error("can't seek to %lu: %s\n", kbpos->offset, g10_errstr(rc));
+       log_error("can't seek to %lu\n", kbpos->offset);
        iobuf_close(a);
        return G10ERR_KEYRING_OPEN;
     }
@@ -724,7 +746,7 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
 {
     RESTBL *rentry;
     IOBUF fp, newfp;
-    int rc;
+    int rc=0;
     char *bakfname = NULL;
     char *tmpfname = NULL;
 
index 6040f4c..2bf3045 100644 (file)
@@ -573,7 +573,7 @@ check_all_keysigs( KBNODE keyblock )
  * Ask and remove invalid signatures are to be removed.
  */
 static int
-remove_keysigs( KBNODE keyblock, int all )
+remove_keysigs( KBNODE keyblock, u32 *keyid, int all )
 {
     KBNODE kbctx;
     KBNODE node;
@@ -588,7 +588,7 @@ remove_keysigs( KBNODE keyblock, int all )
            && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
            PKT_signature *sig = node->pkt->pkt.signature;
 
-           if( all ) {
+           if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) {
                /* fixme: skip self-sig */
            }
 
@@ -609,6 +609,10 @@ remove_keysigs( KBNODE keyblock, int all )
                tty_printf("Public key not available.\n");
            else if( node->flag & 4 )
                tty_printf("The signature could not be checked!\n");
+
+           if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
+               continue; /* do not remove self-signatures */
+
            answer = tty_get("\nRemove this signature? ");
            tty_kill_prompt();
            if( answer_is_yes(answer) ) {
@@ -709,7 +713,7 @@ sign_key( const char *username, STRLIST locusr )
            answer = tty_get("To you want to remove some of the invalid sigs? ");
            tty_kill_prompt();
            if( answer_is_yes(answer) )
-               remove_keysigs( keyblock, 0 );
+               remove_keysigs( keyblock, pkc_keyid, 0 );
            m_free(answer);
        }
     }
@@ -833,7 +837,7 @@ edit_keysigs( const char *username )
 
     clear_kbnode_flags( keyblock );
     check_all_keysigs( keyblock );
-    if( remove_keysigs( keyblock, 1 ) ) {
+    if( remove_keysigs( keyblock, pkc_keyid, 1 ) ) {
        rc = update_keyblock( &kbpos, keyblock );
        if( rc ) {
            log_error("update_keyblock failed: %s\n", g10_errstr(rc) );
index 466dd79..0c2620a 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #include <errno.h>
 #include <assert.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #include <fcntl.h>
+#include <unistd.h>
 
 #include "errors.h"
 #include "iobuf.h"
@@ -1490,15 +1492,25 @@ init_trustdb( int level, const char *dbname )
 
     if( !level || level==1 ) {
        char *fname = dbname? m_strdup( dbname )
-                           : make_filename("~/.g10", "trustdb.g10", NULL );
+                           : make_filename(opt.homedir, "trustdb.g10", NULL );
        if( access( fname, R_OK ) ) {
            if( errno != ENOENT ) {
                log_error("can't access %s: %s\n", fname, strerror(errno) );
                m_free(fname);
                return G10ERR_TRUSTDB;
            }
-           if( level )
+           if( level ) {
+               char *p = strrchr( fname, '/' );
+               assert(p);
+               *p = 0;
+               if( access( fname, F_OK ) ) {
+                   if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) )
+                       log_fatal("can't create directory '%s': %s\n",
+                                   fname, strerror(errno) );
+               }
+               *p = '/';
                create_db( fname );
+           }
        }
        m_free(db_name);
        db_name = fname;
@@ -1944,7 +1956,7 @@ int
 verify_private_data()
 {
     int rc = 0;
-    char *sigfile = make_filename("~/.g10", "sig", NULL );
+    char *sigfile = make_filename(opt.homedir, "g10.sig", NULL );
 
     if( access( sigfile, R_OK ) ) {
        if( errno != ENOENT ) {
@@ -1972,8 +1984,8 @@ int
 sign_private_data()
 {
     int rc;
-    char *sigfile = make_filename("~/.g10", "sig", NULL );
-    char *secring = make_filename("~/.g10", "secring.g10", NULL );
+    char *sigfile = make_filename(opt.homedir, "g10.sig", NULL );
+    char *secring = make_filename(opt.homedir, "secring.g10", NULL );
     STRLIST list = NULL;
 
     add_to_strlist( &list, db_name );
index 88494d9..4693a20 100644 (file)
@@ -1 +1,7 @@
 syntax.h
+mpih-lshift.S
+mpih-add1.S
+mpih-sub1.S
+
+
+
index e69de29..fc7df9f 100644 (file)
@@ -0,0 +1,3 @@
+mpih-mul1.S
+mpih-mul2.S
+mpih-mul3.S
diff --git a/mpi/m68k/mc68020/mpih-mul1.S b/mpi/m68k/mc68020/mpih-mul1.S
new file mode 100644 (file)
index 0000000..16a52a2
--- /dev/null
@@ -0,0 +1,97 @@
+/* mc68020 __mpn_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 the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  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_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)
+ */
+
+
+       TEXT
+       ALIGN
+       GLOBL   C_SYMBOL_NAME(mpihelp_mul_1)
+
+C_SYMBOL_NAME(mpihelp_mul_1:)
+PROLOG(mpihelp_mul_1)
+
+#define res_ptr a0
+#define s1_ptr a1
+#define s1_size d2
+#define s2_limb d4
+
+/* Save used registers on the stack.  */
+       moveml  R(d2)-R(d4),MEM_PREDEC(sp)
+#if 0
+       movel   R(d2),MEM_PREDEC(sp)
+       movel   R(d3),MEM_PREDEC(sp)
+       movel   R(d4),MEM_PREDEC(sp)
+#endif
+
+/* Copy the arguments to registers.  Better use movem? */
+       movel   MEM_DISP(sp,16),R(res_ptr)
+       movel   MEM_DISP(sp,20),R(s1_ptr)
+       movel   MEM_DISP(sp,24),R(s1_size)
+       movel   MEM_DISP(sp,28),R(s2_limb)
+
+       eorw    #1,R(s1_size)
+       clrl    R(d1)
+       lsrl    #1,R(s1_size)
+       bcc     L(L1)
+       subql   #1,R(s1_size)
+       subl    R(d0),R(d0)     /* (d0,cy) <= (0,0) */
+
+L(Loop:)
+       movel   MEM_POSTINC(s1_ptr),R(d3)
+       mulul   R(s2_limb),R(d1):R(d3)
+       addxl   R(d0),R(d3)
+       movel   R(d3),MEM_POSTINC(res_ptr)
+L(L1:) movel   MEM_POSTINC(s1_ptr),R(d3)
+       mulul   R(s2_limb),R(d0):R(d3)
+       addxl   R(d1),R(d3)
+       movel   R(d3),MEM_POSTINC(res_ptr)
+
+       dbf     R(s1_size),L(Loop)
+       clrl    R(d3)
+       addxl   R(d3),R(d0)
+       subl    #0x10000,R(s1_size)
+       bcc     L(Loop)
+
+/* Restore used registers from stack frame.  */
+       moveml  MEM_POSTINC(sp),R(d2)-R(d4)
+#if 0
+       movel   MEM_POSTINC(sp),R(d4)
+       movel   MEM_POSTINC(sp),R(d3)
+       movel   MEM_POSTINC(sp),R(d2)
+#endif
+       rts
+EPILOG(mpihelp_mul_1)
+
+
diff --git a/mpi/m68k/mc68020/mpih-mul2.S b/mpi/m68k/mc68020/mpih-mul2.S
new file mode 100644 (file)
index 0000000..8cbbc54
--- /dev/null
@@ -0,0 +1,87 @@
+/* mc68020 __mpn_addmul_1 -- Multiply a limb vector with a limb and add
+   the result to a second limb vector.
+
+Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  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_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)
+ */
+
+
+       TEXT
+       ALIGN
+       GLOBL   C_SYMBOL_NAME(mpihelp_addmul_1)
+
+C_SYMBOL_NAME(mpihelp_addmul_1:)
+PROLOG(mpihelp_addmul_1)
+
+#define res_ptr a0
+#define s1_ptr a1
+#define s1_size d2
+#define s2_limb d4
+
+/* Save used registers on the stack.  */
+       moveml  R(d2)-R(d5),MEM_PREDEC(sp)
+
+/* Copy the arguments to registers.  Better use movem? */
+       movel   MEM_DISP(sp,20),R(res_ptr)
+       movel   MEM_DISP(sp,24),R(s1_ptr)
+       movel   MEM_DISP(sp,28),R(s1_size)
+       movel   MEM_DISP(sp,32),R(s2_limb)
+
+       eorw    #1,R(s1_size)
+       clrl    R(d1)
+       clrl    R(d5)
+       lsrl    #1,R(s1_size)
+       bcc     L(L1)
+       subql   #1,R(s1_size)
+       subl    R(d0),R(d0)             /* (d0,cy) <= (0,0) */
+
+L(Loop:)
+       movel   MEM_POSTINC(s1_ptr),R(d3)
+       mulul   R(s2_limb),R(d1):R(d3)
+       addxl   R(d0),R(d3)
+       addxl   R(d5),R(d1)
+       addl    R(d3),MEM_POSTINC(res_ptr)
+L(L1:) movel   MEM_POSTINC(s1_ptr),R(d3)
+       mulul   R(s2_limb),R(d0):R(d3)
+       addxl   R(d1),R(d3)
+       addxl   R(d5),R(d0)
+       addl    R(d3),MEM_POSTINC(res_ptr)
+
+       dbf     R(s1_size),L(Loop)
+       addxl   R(d5),R(d0)
+       subl    #0x10000,R(s1_size)
+       bcc     L(Loop)
+
+/* Restore used registers from stack frame.  */
+       moveml  MEM_POSTINC(sp),R(d2)-R(d5)
+
+       rts
+EPILOG(mpihelp_addmul_1)
+
diff --git a/mpi/m68k/mc68020/mpih-mul3.S b/mpi/m68k/mc68020/mpih-mul3.S
new file mode 100644 (file)
index 0000000..8e28ce4
--- /dev/null
@@ -0,0 +1,89 @@
+/* mc68020 __mpn_submul_1 -- Multiply a limb vector with a limb and subtract
+   the result from a second limb vector.
+
+Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  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_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)
+ */
+
+
+       TEXT
+       ALIGN
+       GLOBL   C_SYMBOL_NAME(mpihelp_submul_1)
+
+C_SYMBOL_NAME(mpihelp_submul_1:)
+PROLOG(mpihelp_submul_1)
+
+#define res_ptr a0
+#define s1_ptr a1
+#define s1_size d2
+#define s2_limb d4
+
+/* Save used registers on the stack.  */
+       moveml  R(d2)-R(d5),MEM_PREDEC(sp)
+
+/* Copy the arguments to registers.  Better use movem? */
+       movel   MEM_DISP(sp,20),R(res_ptr)
+       movel   MEM_DISP(sp,24),R(s1_ptr)
+       movel   MEM_DISP(sp,28),R(s1_size)
+       movel   MEM_DISP(sp,32),R(s2_limb)
+
+       eorw    #1,R(s1_size)
+       clrl    R(d1)
+       clrl    R(d5)
+       lsrl    #1,R(s1_size)
+       bcc     L(L1)
+       subql   #1,R(s1_size)
+       subl    R(d0),R(d0)     /* (d0,cy) <= (0,0) */
+
+L(Loop:)
+       movel   MEM_POSTINC(s1_ptr),R(d3)
+       mulul   R(s2_limb),R(d1):R(d3)
+       addxl   R(d0),R(d3)
+       addxl   R(d5),R(d1)
+       subl    R(d3),MEM_POSTINC(res_ptr)
+L(L1:) movel   MEM_POSTINC(s1_ptr),R(d3)
+       mulul   R(s2_limb),R(d0):R(d3)
+       addxl   R(d1),R(d3)
+       addxl   R(d5),R(d0)
+       subl    R(d3),MEM_POSTINC(res_ptr)
+
+       dbf     R(s1_size),L(Loop)
+       addxl   R(d5),R(d0)
+       subl    #0x10000,R(s1_size)
+       bcc     L(Loop)
+
+/* Restore used registers from stack frame.  */
+       moveml  MEM_POSTINC(sp),R(d2)-R(d5)
+
+       rts
+EPILOG(mpihelp_submul_1)
+
+
diff --git a/mpi/m68k/mpih-add1.S b/mpi/m68k/mpih-add1.S
new file mode 100644 (file)
index 0000000..b3812c7
--- /dev/null
@@ -0,0 +1,85 @@
+/* mc68020 __mpn_add_n -- Add two limb vectors of the same length > 0 and store
+   sum in a third limb vector.
+
+Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  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 + 16)
+ *                mpi_size_t size)     (sp + 12)
+ */
+
+
+       TEXT
+       ALIGN
+       GLOBL   C_SYMBOL_NAME(mpihelp_add_n)
+
+C_SYMBOL_NAME(mpihelp_add_n:)
+PROLOG(mpihelp_add_n)
+       /* Save used registers on the stack.  */
+       movel   R(d2),MEM_PREDEC(sp)
+       movel   R(a2),MEM_PREDEC(sp)
+
+       /* Copy the arguments to registers.  Better use movem?  */
+       movel   MEM_DISP(sp,12),R(a2)
+       movel   MEM_DISP(sp,16),R(a0)
+       movel   MEM_DISP(sp,20),R(a1)
+       movel   MEM_DISP(sp,24),R(d2)
+
+       eorw    #1,R(d2)
+       lsrl    #1,R(d2)
+       bcc     L(L1)
+       subql   #1,R(d2)        /* clears cy as side effect */
+
+L(Loop:)
+       movel   MEM_POSTINC(a0),R(d0)
+       movel   MEM_POSTINC(a1),R(d1)
+       addxl   R(d1),R(d0)
+       movel   R(d0),MEM_POSTINC(a2)
+L(L1:) movel   MEM_POSTINC(a0),R(d0)
+       movel   MEM_POSTINC(a1),R(d1)
+       addxl   R(d1),R(d0)
+       movel   R(d0),MEM_POSTINC(a2)
+
+       dbf     R(d2),L(Loop)           /* loop until 16 lsb of %4 == -1 */
+       subxl   R(d0),R(d0)     /* d0 <= -cy; save cy as 0 or -1 in d0 */
+       subl    #0x10000,R(d2)
+       bcs     L(L2)
+       addl    R(d0),R(d0)     /* restore cy */
+       bra     L(Loop)
+
+L(L2:)
+       negl    R(d0)
+
+       /* Restore used registers from stack frame.  */
+       movel   MEM_POSTINC(sp),R(a2)
+       movel   MEM_POSTINC(sp),R(d2)
+
+       rts
+EPILOG(mpihelp_add_n)
+
+
diff --git a/mpi/m68k/mpih-shift.S b/mpi/m68k/mpih-shift.S
new file mode 100644 (file)
index 0000000..a920874
--- /dev/null
@@ -0,0 +1,286 @@
+/* mc68020 __mpn_lshift -- Shift left a low-level natural-number integer.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  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_lshift( mpi_ptr_t wp,       (sp + 4)
+ *                mpi_ptr_t up,        (sp + 8)
+ *                mpi_size_t usize,    (sp + 12)
+ *                unsigned cnt)        (sp + 16)
+ */
+
+#define res_ptr a1
+#define s_ptr a0
+#define s_size d6
+#define cnt d4
+
+       TEXT
+       ALIGN
+       GLOBL   C_SYMBOL_NAME(mpihelp_lshift)
+
+C_SYMBOL_NAME(mpihelp_lshift:)
+PROLOG(mpihelp_lshift)
+
+       /* Save used registers on the stack.  */
+       moveml  R(d2)-R(d6)/R(a2),MEM_PREDEC(sp)
+
+       /* Copy the arguments to registers.  */
+       movel   MEM_DISP(sp,28),R(res_ptr)
+       movel   MEM_DISP(sp,32),R(s_ptr)
+       movel   MEM_DISP(sp,36),R(s_size)
+       movel   MEM_DISP(sp,40),R(cnt)
+
+       moveql  #1,R(d5)
+       cmpl    R(d5),R(cnt)
+       bne     L(Lnormal)
+       cmpl    R(s_ptr),R(res_ptr)
+       bls     L(Lspecial)             /* jump if s_ptr >= res_ptr */
+#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
+       lea     MEM_INDX1(s_ptr,s_size,l,4),R(a2)
+#else /* not mc68020 */
+       movel   R(s_size),R(d0)
+       asll    #2,R(d0)
+       lea     MEM_INDX(s_ptr,d0,l),R(a2)
+#endif
+       cmpl    R(res_ptr),R(a2)
+       bls     L(Lspecial)             /* jump if res_ptr >= s_ptr + s_size */
+
+L(Lnormal:)
+       moveql  #32,R(d5)
+       subl    R(cnt),R(d5)
+
+#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
+       lea     MEM_INDX1(s_ptr,s_size,l,4),R(s_ptr)
+       lea     MEM_INDX1(res_ptr,s_size,l,4),R(res_ptr)
+#else /* not mc68000 */
+       movel   R(s_size),R(d0)
+       asll    #2,R(d0)
+       addl    R(s_size),R(s_ptr)
+       addl    R(s_size),R(res_ptr)
+#endif
+       movel   MEM_PREDEC(s_ptr),R(d2)
+       movel   R(d2),R(d0)
+       lsrl    R(d5),R(d0)             /* compute carry limb */
+
+       lsll    R(cnt),R(d2)
+       movel   R(d2),R(d1)
+       subql   #1,R(s_size)
+       beq     L(Lend)
+       lsrl    #1,R(s_size)
+       bcs     L(L1)
+       subql   #1,R(s_size)
+
+L(Loop:)
+       movel   MEM_PREDEC(s_ptr),R(d2)
+       movel   R(d2),R(d3)
+       lsrl    R(d5),R(d3)
+       orl     R(d3),R(d1)
+       movel   R(d1),MEM_PREDEC(res_ptr)
+       lsll    R(cnt),R(d2)
+L(L1:)
+       movel   MEM_PREDEC(s_ptr),R(d1)
+       movel   R(d1),R(d3)
+       lsrl    R(d5),R(d3)
+       orl     R(d3),R(d2)
+       movel   R(d2),MEM_PREDEC(res_ptr)
+       lsll    R(cnt),R(d1)
+
+       dbf     R(s_size),L(Loop)
+       subl    #0x10000,R(s_size)
+       bcc     L(Loop)
+
+L(Lend:)
+       movel   R(d1),MEM_PREDEC(res_ptr) /* store least significant limb */
+
+/* Restore used registers from stack frame.  */
+       moveml  MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
+       rts
+
+/* 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.  */
+
+L(Lspecial:)
+       clrl    R(d0)                   /* initialize carry */
+       eorw    #1,R(s_size)
+       lsrl    #1,R(s_size)
+       bcc     L(LL1)
+       subql   #1,R(s_size)
+
+L(LLoop:)
+       movel   MEM_POSTINC(s_ptr),R(d2)
+       addxl   R(d2),R(d2)
+       movel   R(d2),MEM_POSTINC(res_ptr)
+L(LL1:)
+       movel   MEM_POSTINC(s_ptr),R(d2)
+       addxl   R(d2),R(d2)
+       movel   R(d2),MEM_POSTINC(res_ptr)
+
+       dbf     R(s_size),L(LLoop)
+       addxl   R(d0),R(d0)             /* save cy in lsb */
+       subl    #0x10000,R(s_size)
+       bcs     L(LLend)
+       lsrl    #1,R(d0)                /* restore cy */
+       bra     L(LLoop)
+
+L(LLend:)
+/* Restore used registers from stack frame.  */
+       moveml  MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
+       rts
+EPILOG(mpihelp_lshift)
+
+
+
+
+/*******************
+ * 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)
+ */
+
+#define res_ptr a1
+#define s_ptr a0
+#define s_size d6
+#define cnt d4
+
+       TEXT
+       ALIGN
+       GLOBL   C_SYMBOL_NAME(mpihelp_rshift)
+
+C_SYMBOL_NAME(mpihelp_rshift:)
+PROLOG(mpihelp_rshift)
+       /* Save used registers on the stack.  */
+       moveml  R(d2)-R(d6)/R(a2),MEM_PREDEC(sp)
+
+       /* Copy the arguments to registers.  */
+       movel   MEM_DISP(sp,28),R(res_ptr)
+       movel   MEM_DISP(sp,32),R(s_ptr)
+       movel   MEM_DISP(sp,36),R(s_size)
+       movel   MEM_DISP(sp,40),R(cnt)
+
+       moveql  #1,R(d5)
+       cmpl    R(d5),R(cnt)
+       bne     L(Rnormal)
+       cmpl    R(res_ptr),R(s_ptr)
+       bls     L(Lspecial)             /* jump if res_ptr >= s_ptr */
+#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
+       lea     MEM_INDX1(res_ptr,s_size,l,4),R(a2)
+#else /* not mc68020 */
+       movel   R(s_size),R(d0)
+       asll    #2,R(d0)
+       lea     MEM_INDX(res_ptr,d0,l),R(a2)
+#endif
+       cmpl    R(s_ptr),R(a2)
+       bls     L(Lspecial)             /* jump if s_ptr >= res_ptr + s_size */
+
+L(Rnormal:)
+       moveql  #32,R(d5)
+       subl    R(cnt),R(d5)
+       movel   MEM_POSTINC(s_ptr),R(d2)
+       movel   R(d2),R(d0)
+       lsll    R(d5),R(d0)             /* compute carry limb */
+
+       lsrl    R(cnt),R(d2)
+       movel   R(d2),R(d1)
+       subql   #1,R(s_size)
+       beq     L(Rend)
+       lsrl    #1,R(s_size)
+       bcs     L(R1)
+       subql   #1,R(s_size)
+
+L(Roop:)
+       movel   MEM_POSTINC(s_ptr),R(d2)
+       movel   R(d2),R(d3)
+       lsll    R(d5),R(d3)
+       orl     R(d3),R(d1)
+       movel   R(d1),MEM_POSTINC(res_ptr)
+       lsrl    R(cnt),R(d2)
+L(R1:)
+       movel   MEM_POSTINC(s_ptr),R(d1)
+       movel   R(d1),R(d3)
+       lsll    R(d5),R(d3)
+       orl     R(d3),R(d2)
+       movel   R(d2),MEM_POSTINC(res_ptr)
+       lsrl    R(cnt),R(d1)
+
+       dbf     R(s_size),L(Roop)
+       subl    #0x10000,R(s_size)
+       bcc     L(Roop)
+
+L(Rend:)
+       movel   R(d1),MEM(res_ptr) /* store most significant limb */
+
+/* Restore used registers from stack frame.  */
+       moveml  MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
+       rts
+
+/* We loop from most 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.  */
+
+L(Lspecial:)
+#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
+       lea     MEM_INDX1(s_ptr,s_size,l,4),R(s_ptr)
+       lea     MEM_INDX1(res_ptr,s_size,l,4),R(res_ptr)
+#else /* not mc68000 */
+       movel   R(s_size),R(d0)
+       asll    #2,R(d0)
+       addl    R(s_size),R(s_ptr)
+       addl    R(s_size),R(res_ptr)
+#endif
+
+       clrl    R(d0)                   /* initialize carry */
+       eorw    #1,R(s_size)
+       lsrl    #1,R(s_size)
+       bcc     L(LR1)
+       subql   #1,R(s_size)
+
+L(LRoop:)
+       movel   MEM_PREDEC(s_ptr),R(d2)
+       roxrl   #1,R(d2)
+       movel   R(d2),MEM_PREDEC(res_ptr)
+L(LR1:)
+       movel   MEM_PREDEC(s_ptr),R(d2)
+       roxrl   #1,R(d2)
+       movel   R(d2),MEM_PREDEC(res_ptr)
+
+       dbf     R(s_size),L(LRoop)
+       roxrl   #1,R(d0)                /* save cy in msb */
+       subl    #0x10000,R(s_size)
+       bcs     L(LRend)
+       addl    R(d0),R(d0)             /* restore cy */
+       bra     L(LRoop)
+
+L(LRend:)
+/* Restore used registers from stack frame.  */
+       moveml  MEM_POSTINC(sp),R(d2)-R(d6)/R(a2)
+       rts
+EPILOG(mpihelp_rshift)
+
+
+
+
diff --git a/mpi/m68k/mpih-sub1.S b/mpi/m68k/mpih-sub1.S
new file mode 100644 (file)
index 0000000..8d8ef0b
--- /dev/null
@@ -0,0 +1,85 @@
+/* mc68020 __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and
+   store difference in a third limb vector.
+
+Copyright (C) 1992, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library 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 Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB.  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_sub_n( mpi_ptr_t res_ptr,  (sp + 4)
+ *                mpi_ptr_t s1_ptr,    (sp + 8)
+ *                mpi_ptr_t s2_ptr,    (sp + 16)
+ *                mpi_size_t size)     (sp + 12)
+ */
+
+
+       TEXT
+       ALIGN
+       GLOBL   C_SYMBOL_NAME(mpihelp_sub_n)
+
+C_SYMBOL_NAME(mpihelp_sub_n:)
+PROLOG(mpihelp_sub_n)
+/* Save used registers on the stack.  */
+       movel   R(d2),MEM_PREDEC(sp)
+       movel   R(a2),MEM_PREDEC(sp)
+
+/* Copy the arguments to registers.  Better use movem? */
+       movel   MEM_DISP(sp,12),R(a2)
+       movel   MEM_DISP(sp,16),R(a0)
+       movel   MEM_DISP(sp,20),R(a1)
+       movel   MEM_DISP(sp,24),R(d2)
+
+       eorw    #1,R(d2)
+       lsrl    #1,R(d2)
+       bcc     L(L1)
+       subql   #1,R(d2)        /* clears cy as side effect */
+
+L(Loop:)
+       movel   MEM_POSTINC(a0),R(d0)
+       movel   MEM_POSTINC(a1),R(d1)
+       subxl   R(d1),R(d0)
+       movel   R(d0),MEM_POSTINC(a2)
+L(L1:) movel   MEM_POSTINC(a0),R(d0)
+       movel   MEM_POSTINC(a1),R(d1)
+       subxl   R(d1),R(d0)
+       movel   R(d0),MEM_POSTINC(a2)
+
+       dbf     R(d2),L(Loop)           /* loop until 16 lsb of %4 == -1 */
+       subxl   R(d0),R(d0)     /* d0 <= -cy; save cy as 0 or -1 in d0 */
+       subl    #0x10000,R(d2)
+       bcs     L(L2)
+       addl    R(d0),R(d0)     /* restore cy */
+       bra     L(Loop)
+
+L(L2:)
+       negl    R(d0)
+
+/* Restore used registers from stack frame.  */
+       movel   MEM_POSTINC(sp),R(a2)
+       movel   MEM_POSTINC(sp),R(d2)
+
+       rts
+EPILOG(mpihelp_sub_n)
+
+
index 53ef356..dcded3e 100644 (file)
@@ -44,10 +44,10 @@ mpi_invm( MPI x, MPI a, MPI n )
     v1 = mpi_alloc_set_ui(0);
     v2 = mpi_alloc_set_ui(1);
     v3 = mpi_copy(v);
-    q  = mpi_alloc( mpi_get_nlimbs(u) );
-    t1 = mpi_alloc( mpi_get_nlimbs(u) );
-    t2 = mpi_alloc( mpi_get_nlimbs(u) );
-    t3 = mpi_alloc( mpi_get_nlimbs(u) );
+    q  = mpi_alloc( mpi_get_nlimbs(u)+1 );
+    t1 = mpi_alloc( mpi_get_nlimbs(u)+1 );
+    t2 = mpi_alloc( mpi_get_nlimbs(u)+1 );
+    t3 = mpi_alloc( mpi_get_nlimbs(u)+1 );
     while( mpi_cmp_ui( v3, 0 ) ) {
        mpi_fdiv_q( q, u3, v3 );
        mpi_mul(t1, v1, q); mpi_mul(t2, v2, q); mpi_mul(t3, v3, q);
index 770fe9e..a6d2a34 100644 (file)
@@ -1,3 +1,7 @@
+Tue Feb 17 19:43:44 1998  Werner Koch  (wk@isil.d.shuttle.de)
+
+       * memory.c (dump_table_at_exit): New.
+
 Mon Feb 16 10:07:28 1998  Werner Koch  (wk@isil.d.shuttle.de)
 
        * argparse.c (show_version, show_help, default_strusage): Changed
index cd4dc81..6633b94 100644 (file)
@@ -101,6 +101,7 @@ static unsigned memtbl_size;        /* number of allocated entries */
 static unsigned memtbl_len;    /* number of used entries */
 static struct memtbl_entry *memtbl_unused;/* to keep track of unused entries */
 
+static void dump_table_at_exit(void);
 static void dump_table(void);
 static void check_allmem( const char *info );
 
@@ -135,8 +136,7 @@ add_entry( byte *p, unsigned n, int mode, const char *info, const char *by )
                    membug("memory debug table malloc failed\n");
                index = 0;
                memtbl_len = 1;
-               if( DBG_MEMSTAT )
-                   atexit( dump_table );
+               atexit( dump_table_at_exit );
            }
            else { /* realloc */
                unsigned n = memtbl_size / 4; /* enlarge by 25% */
@@ -264,6 +264,14 @@ dump_entry(struct memtbl_entry *e )
 
 }
 
+
+static void
+dump_table_at_exit( void)
+{
+    if( DBG_MEMSTAT )
+       dump_table();
+}
+
 static void
 dump_table( void)
 {