Add set -e.
authormdw <mdw>
Sun, 4 Apr 2004 19:42:59 +0000 (19:42 +0000)
committermdw <mdw>
Sun, 4 Apr 2004 19:42:59 +0000 (19:42 +0000)
15 files changed:
.cvsignore
Makefile.m4
dsig.c
gdsa.c [new file with mode: 0644]
gdsa.h [new file with mode: 0644]
genmodes
ghash-def.h
gkcdsa.c [new file with mode: 0644]
gkcdsa.h [new file with mode: 0644]
has160.c [new file with mode: 0644]
has160.h [new file with mode: 0644]
hashsum.c
tests/gdsa [new file with mode: 0644]
tests/gkcdsa [new file with mode: 0644]
tests/has160 [new file with mode: 0644]

index 8eae633..6aeb347 100644 (file)
@@ -285,3 +285,7 @@ sha224-mgf.c
 sha224-mgf.h
 junk
 deb-build
+has160-hmac.c
+has160-hmac.h
+has160-mgf.c
+has160-mgf.h
index bd832ab..3f2672d 100644 (file)
@@ -1,6 +1,6 @@
 ## -*-m4-*-
 ##
-## $Id: Makefile.m4,v 1.78 2004/04/04 19:04:11 mdw Exp $
+## $Id: Makefile.m4,v 1.79 2004/04/04 19:42:59 mdw Exp $
 ##
 ## Makefile for Catacomb
 ##
@@ -29,6 +29,9 @@
 ##----- Revision history ----------------------------------------------------
 ##
 ## $Log: Makefile.m4,v $
+## Revision 1.79  2004/04/04 19:42:59  mdw
+## Add set -e.
+##
 ## Revision 1.78  2004/04/04 19:04:11  mdw
 ## Raw I/O of elliptic curve points and group elements.
 ##
@@ -319,7 +322,7 @@ _(serpent) _(noekeon)')
 define(`cipher_modes', `_(ecb) _(cbc) _(cfb) _(ofb) _(counter)')
 
 define(`hashes', `dnl
-_(md5) _(md4) _(md2) _(tiger) dnl
+_(md5) _(md4) _(md2) _(tiger) _(has160) dnl
 _(sha) _(sha224) _(sha256) _(sha384) _(sha512) dnl
 _(rmd128) _(rmd160) _(rmd256) _(rmd320)')
 define(`hash_modes', `_(mgf) _(hmac)')
@@ -367,8 +370,24 @@ ptab.c: ptab.in p-gentab.awk mpdump
        $(srcdir)/p-gentab.awk <$(srcdir)/ptab.in >ptab.c.new
        mv ptab.c.new ptab.c
 
+gciphertab.c: gengctab
+       $(srcdir)/gengctab gccipher gcipher >gciphertab.c.new \
+               "lit(join(`ciphers', `-', `cipher_modes')) \
+               rc4 seal" 
+       mv gciphertab.c.new gciphertab.c
+
+gmactab.c: gengctab
+       $(srcdir)/gengctab gcmac gmac >gmactab.c.new \
+               "lit(join(`hashes', `-', `_(hmac)'))" 
+       mv gmactab.c.new gmactab.c
+
+ghashtab.c: gengctab
+       $(srcdir)/gengctab gchash ghash >ghashtab.c.new \
+               "lit(`hashes')"
+       mv ghashtab.c.new ghashtab.c
+
 BUILT_SOURCES = \
-       getdate.c modes-stamp \
+       getdate.c modes-stamp gciphertab.c gmactab.c ghashtab.c \
        addsuffix(join(`ciphers', `-', `cipher_modes'), `.c') \
        addsuffix(join(`ciphers', `-', `cipher_modes'), `.h') \
        addsuffix(join(`hashes', `-', `hash_modes'), `.c') \
@@ -393,7 +412,7 @@ pkginclude_HEADERS = \
        gfx.h gf.h gfreduce.h gfn.h \
        primetab.h pfilt.h rabin.h \
        pgen.h prim.h strongprime.h limlee.h keycheck.h \
-       bbs.h rsa.h dh.h dsarand.h dsa.h \
+       bbs.h rsa.h dh.h dsarand.h dsa.h gdsa.h gkcdsa.h \
        oaep.h pkcs1.h pss.h tlsprf.h sslprf.h \
        gfshare.h share.h \
        rho.h \
@@ -437,6 +456,7 @@ define(`PGEN_SOURCES',
        rsa-priv.c rsa-pub.c rsa-gen.c rsa-recover.c rsa-fetch.c \
        dh-gen.c dh-limlee.c dh-check.c dh-fetch.c dh-param.c \
        dsarand.c dsa-sign.c dsa-verify.c dsa-gen.c dsa-check.c \
+       gdsa.c gkcdsa.c \
        key-data.c key-flags.c key-text.c key-binary.c key-pass.c \
        key-pack.c key-misc.c key-file.c key-attr.c key-io.c key-moan.c \
        key-error.c key-fetch.c \
@@ -450,6 +470,7 @@ libcatacomb_la_SOURCES = \
        oaep.c pkcs1.c pss.c tlsprf.c sslprf.c \
        gfshare.c \
        MP_SOURCES karatsuba.h \
+       gciphertab.c ghashtab.c gmactab.c \
        des-base.c des-base.h \
        desx-tab.h \
        rc2-tab.h \
@@ -543,7 +564,7 @@ man_MANS = key.1 hashsum.1 keyring.5 pixie.1
 ## --- Other handy definitions ---
 
 EXTRA_DIST = \
-       Makefile.m4 genmodes $(man_MANS) xpixie group-test.c \
+       Makefile.m4 genmodes gengctab $(man_MANS) xpixie group-test.c \
        ectab.in ec-gentab.awk ptab.in p-gentab.awk \
        README.cipher README.hash README.random README.mp \
        debian/rules debian/copyright debian/control debian/changelog \
@@ -551,7 +572,9 @@ EXTRA_DIST = \
        debian/catacomb-bin.prerm debian/catacomb-bin.templates
 
 dist-hook:
-       @ln getdate.c $(distdir) || ln $(srcdir)/getdate.c $(distdir) || true
+       @for i in getdate.c gciphertab.c ghashtab.c gmactab.c; do \
+         ln $$i $(distdir) || ln $(srcdir)/$$i $(distdir) || true; \
+       done
        @echo datestamp >$(distdir)/modes-stamp || true
        @for i in calc tests; do \
          mkdir $(distdir)/$$i; \
@@ -618,6 +641,8 @@ CTESTRIG(ec-test)
 CTESTRIG(ec-info)
 CTESTRIG(dh-param)
 CTESTRIG(group-test)
+CTESTRIG(gdsa)
+CTESTRIG(gkcdsa)
 CTESTRIG(pgen)
 CTESTRIG(dsa-gen)
 CTESTRIG(dsa-sign)
diff --git a/dsig.c b/dsig.c
index c5eb5af..6a67990 100644 (file)
--- a/dsig.c
+++ b/dsig.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: dsig.c,v 1.7 2001/02/23 09:04:17 mdw Exp $
+ * $Id: dsig.c,v 1.8 2004/04/04 19:42:59 mdw Exp $
  *
  * Verify signatures on distribuitions of files
  *
@@ -30,6 +30,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: dsig.c,v $
+ * Revision 1.8  2004/04/04 19:42:59  mdw
+ * Add set -e.
+ *
  * Revision 1.7  2001/02/23 09:04:17  mdw
  * Add new hash functions.  Provide full help for subcommands.  Run the
  * hash function over parts of the header in a canonical order.
 #include "rsa.h"
 #include "pkcs1.h"
 
-#include "md2.h"
-#include "md4.h"
-#include "md5.h"
-#include "rmd128.h"
-#include "rmd160.h"
-#include "rmd256.h"
-#include "rmd320.h"
-#include "sha.h"
-#include "sha256.h"
-#include "sha384.h"
-#include "sha512.h"
-#include "tiger.h"
-
 /*----- Digital signature algorithm ---------------------------------------*/
 
 static int dsasign(key *k, const void *m, size_t msz, dstr *d)
@@ -206,9 +196,6 @@ typedef struct sig {
                const void */*s*/, size_t /*ssz*/);
 } sig;
 
-static const gchash *hashtab[] = {
-  &rmd160, &tiger, &sha, &sha256, &sha384, &sha512,
-  &rmd128, &rmd256, &rmd320, &md5, &md4, &md2, 0 };
 static sig sigtab[] = {
   { "dsa", "dsig-dsa", dsasign, dsaverify },
   { "rsa", "dsig-rsa", rsasign, rsaverify },
@@ -226,9 +213,9 @@ static sig sigtab[] = {
 
 static const gchash *gethash(const char *name)
 {
-  const gchash **g, *gg = 0;
+  const gchash *const *g, *gg = 0;
   size_t sz = strlen(name);
-  for (g = hashtab; *g; g++) {
+  for (g = ghashtab; *g; g++) {
     if (strncmp(name, (*g)->name, sz) == 0) {
       if ((*g)->name[sz] == 0) {
        gg = *g;
diff --git a/gdsa.c b/gdsa.c
new file mode 100644 (file)
index 0000000..8723847
--- /dev/null
+++ b/gdsa.c
@@ -0,0 +1,264 @@
+/* -*-c-*-
+ *
+ * $Id: gdsa.c,v 1.1 2004/04/04 19:42:59 mdw Exp $
+ *
+ * Generalized version of DSA
+ *
+ * (c) 2004 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------* 
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb 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.
+ * 
+ * Catacomb 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 Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: gdsa.c,v $
+ * Revision 1.1  2004/04/04 19:42:59  mdw
+ * Add set -e.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "gdsa.h"
+#include "group.h"
+#include "ghash.h"
+#include "mpbarrett.h"
+#include "mprand.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @gdsa_beginhash@ --- *
+ *
+ * Arguments:  @const gdsa *c@ = pointer to the context structure
+ *
+ * Returns:    A hashing context for you to hash the message.
+ *
+ * Use:                Initializes a hash function correctly for you to hash a
+ *             message.  Requires @h@.
+ */
+
+ghash *gdsa_beginhash(const gdsa *c) { return (GH_INIT(c->h)); }
+
+/* --- @gdsa_endhash@ --- *
+ *
+ * Arguments:  @const gdsa *c@ = pointer to the context structure
+ *             @ghash *h@ = the hashing context
+ *
+ * Returns:    ---
+ *
+ * Use:                Does any final thing that DSA wants to do when hashing a
+ *             message.  (Actually, there's nothing.)  The hashing context
+ *             isn't finalized.
+ */
+
+void gdsa_endhash(gdsa *c, ghash *h) { ; }
+
+/* --- @gdsa_sign@ --- *
+ *
+ * Arguments:  @const gdsa *c@ = my context structure
+ *             @gdsa_sig *s@ = where to put the signature (initialized)
+ *             @const void *m@ = pointer to message hash
+ *             @mp *k@ = random exponent for this message or null
+ *
+ * Returns:    ---
+ *
+ * Use:                Signs a message.  Requires @g@, @u@, @h@, and @r@ if @k@ is
+ *             null.  This is a better idea than inventing @k@ yourself.
+ */
+
+void gdsa_sign(const gdsa *c, gdsa_sig *s, const void *m, mp *k)
+{
+  group *g = c->g;
+  mp *mr = mp_loadb(MP_NEW, m, c->h->hashsz);
+  ge *z = G_CREATE(g);
+  mp *sr = s->r, *ss = s->s;
+  mpbarrett b;
+
+  if (k) { MP_COPY(k); goto have_k; }
+new_k:
+  k = mprand_range(k, g->r, c->r, 0);
+have_k:
+  if (MP_ISZERO(k)) goto new_k;
+  G_EXP(g, z, g->g, k);
+  sr = G_TOINT(g, sr, z); assert(sr);
+  if (MP_ISZERO(sr)) goto new_k;
+
+  mp_div(0, &sr, sr, g->r);
+  mpbarrett_create(&b, g->r);
+  ss = mp_mul(ss, sr, c->u); ss = mpbarrett_reduce(&b, ss, ss);
+  ss = mp_add(ss, ss, mr); mp_div(0, &ss, ss, g->r);
+  mp_gcd(0, 0, &k, g->r, k);
+  ss = mp_mul(ss, ss, k); ss = mpbarrett_reduce(&b, ss, ss);
+  s->r = sr; s->s = ss;
+  mp_drop(k); mp_drop(mr); mpbarrett_destroy(&b); G_DESTROY(g, z);
+}
+
+/* --- @gdsa_verify@ --- *
+ *
+ * Arguments:  @const gdsa *c@ = my context structure
+ *             @const gdsa_sig *s@ = the signature to verify
+ *             @const void *m@ = pointer to message hash
+ *
+ * Returns:    Zero if OK, negative on failure.
+ *
+ * Use:                Checks a signature on a message,  Requires @g@, @p@ and @h@.
+ */
+
+int gdsa_verify(const gdsa *c, const gdsa_sig *s, const void *m)
+{
+  group *g = c->g;
+  group_expfactor e[2];
+  mpbarrett b;
+  mp *h = MP_NEW, *t;
+  ge *w;
+  int rc = -1;
+
+  if (MP_CMP(s->r, <, MP_ONE) || MP_CMP(s->r, >=, g->r) ||
+      MP_CMP(s->s, <, MP_ONE) || MP_CMP(s->s, >=, g->r))
+    return (-1);
+  mpbarrett_create(&b, g->r); mp_gcd(0, 0, &h, g->r, s->s);
+  e[0].base = g->g; e[1].base = c->p;
+  t = mp_loadb(MP_NEW, m, c->h->hashsz); mp_div(0, &t, t, g->r);
+  t = mp_mul(t, t, h); e[0].exp = t = mpbarrett_reduce(&b, t, t);
+  h = mp_mul(h, s->r, h); e[1].exp = h = mpbarrett_reduce(&b, h, h);
+  w = G_CREATE(g); G_MEXP(g, w, e, 2);
+  t = G_TOINT(g, t, w); if (!t) goto done;
+  mp_div(0, &t, t, g->r); if (MP_EQ(t, s->r)) rc = 0;
+done:
+  G_DESTROY(g, w); mp_drop(t); mp_drop(h); mpbarrett_destroy(&b);
+  return (rc);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+static group *getgroup(const char *p) {
+  group *g; qd_parse qd;
+  qd.p = p; qd.e = 0; g = group_parse(&qd);
+  if (g && !qd_eofp(&qd)) { G_DESTROYGROUP(g); g = 0; qd.e = "junk at eof"; }
+  if (!g) { fprintf(stderr, "bad group string `%.*s|%s': %s\n", qd.p - p,
+                   p, qd.p, qd.e); exit(1); }
+  return (g);
+}
+
+static ge *getge(group *g, const char *p) {
+  ge *x = G_CREATE(g);
+  if (group_readstring(g, x, p, 0)) {
+    fprintf(stderr, "bad group element `%s'\n", p);
+    exit(1);
+  }
+  return (x);
+}
+
+static void showge(group *g, const char *p, ge *x) {
+  fprintf(stderr, "*** %s = ", p); group_writefile(g, x, stderr);
+  putc('\n', stderr);
+}
+
+static void showmp(const char *p, mp *x, int r) {
+  fprintf(stderr, "*** %s = ", p); mp_writefile(x, stderr, r); 
+  putc('\n', stderr);
+}
+
+static int tsign(dstr *v)
+{
+  gdsa c;
+  gdsa_sig s, ss = GDSA_SIG_INIT;
+  ghash *h;
+  mp *k;
+  int ok = 1;
+
+  c.g = getgroup(v[0].buf); c.h = ghash_byname(v[1].buf);
+  c.u = *(mp **)v[2].buf; k = *(mp **)v[4].buf;
+  s.r = *(mp **)v[5].buf; s.s = *(mp **)v[6].buf;
+
+  h = gdsa_beginhash(&c);
+  GH_HASH(h, v[3].buf, v[3].len);
+  gdsa_endhash(&c, h);
+  gdsa_sign(&c, &ss, GH_DONE(h, 0), k);
+  if (!MP_EQ(s.r, ss.r) || !MP_EQ(s.s, ss.s)) {
+    ok = 0;
+    fprintf(stderr, "*** sign failed!\n");
+    fprintf(stderr, "*** group: %s\n", v[0].buf);
+    fprintf(stderr, "*** hash: %s\n", c.h->name);
+    showmp("private key", c.u, 16);
+    fprintf(stderr, "*** message: `%s'\n", v[3].buf);
+    showmp("computed r", ss.r, 16); showmp("computed s", ss.s, 16);
+    showmp("expected r", s.r, 16); showmp("expected s", s.s, 16);
+  }
+  mp_drop(s.r); mp_drop(s.s); mp_drop(ss.r); mp_drop(ss.s);
+  mp_drop(k); mp_drop(c.u); G_DESTROYGROUP(c.g); GH_DESTROY(h);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int tverify(dstr *v)
+{
+  gdsa c;
+  gdsa_sig s;
+  ghash *h;
+  int rc, erc;
+  int ok = 1;
+
+  c.g = getgroup(v[0].buf); c.h = ghash_byname(v[1].buf);
+  c.p = getge(c.g, v[2].buf);
+  s.r = *(mp **)v[4].buf; s.s = *(mp **)v[5].buf;
+  erc = *(int *)v[6].buf;
+
+  h = gdsa_beginhash(&c);
+  GH_HASH(h, v[3].buf, v[3].len);
+  gdsa_endhash(&c, h);
+  rc = gdsa_verify(&c, &s, GH_DONE(h, 0));
+  if (!rc != !erc) {
+    ok = 0;
+    fprintf(stderr, "*** verify failed!\n");
+    fprintf(stderr, "*** group: %s\n", v[0].buf);
+    fprintf(stderr, "*** hash: %s\n", c.h->name);
+    showge(c.g, "public key", c.p);
+    fprintf(stderr, "*** message: `%s'\n", v[3].buf);
+    showmp("sig r", s.r, 16); showmp("sig s", s.s, 16);
+    fprintf(stderr, "*** expected %s\n", !erc ? "pass" : "fail");
+  }
+  mp_drop(s.r); mp_drop(s.s); G_DESTROY(c.g, c.p); G_DESTROYGROUP(c.g);
+  GH_DESTROY(h);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static const test_chunk tests[] = {
+  { "sign", tsign, { &type_string, &type_string, &type_mp, &type_string,
+                    &type_mp, &type_mp, &type_mp } },
+  { "verify", tverify, { &type_string, &type_string, &type_string,
+                        &type_string, &type_mp, &type_mp, &type_int } },
+  { 0 }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/tests/gdsa");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/gdsa.h b/gdsa.h
new file mode 100644 (file)
index 0000000..6d88a4d
--- /dev/null
+++ b/gdsa.h
@@ -0,0 +1,140 @@
+/* -*-c-*-
+ *
+ * $Id: gdsa.h,v 1.1 2004/04/04 19:42:59 mdw Exp $
+ *
+ * Generalized version of DSA
+ *
+ * (c) 2004 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------* 
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb 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.
+ * 
+ * Catacomb 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 Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: gdsa.h,v $
+ * Revision 1.1  2004/04/04 19:42:59  mdw
+ * Add set -e.
+ *
+ */
+
+#ifndef CATACOMB_GDSA_H
+#define CATACOMB_GDSA_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+#ifndef CATACOMB_GROUP_H
+#  include "group.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+/* --- GDSA context --- *
+ *
+ * You don't need to fill in all of this stuff.  See the description of the
+ * function you want to use to find out what members are needed.
+ */
+
+typedef struct gdsa {
+  group *g;                            /* The group we work in */
+  mp *u;                               /* Private key, for signing */
+  ge *p;                               /* Public key, for verifying */
+  grand *r;                            /* Random number source */
+  const gchash *h;                     /* Hash function */
+} gdsa;
+
+/* --- GDSA signatures --- */
+
+typedef struct gdsa_sig { mp *r, *s; } gdsa_sig;
+#define GDSA_SIG_INIT { MP_NEW, MP_NEW }
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @gdsa_beginhash@ --- *
+ *
+ * Arguments:  @const gdsa *c@ = pointer to the context structure
+ *
+ * Returns:    A hashing context for you to hash the message.
+ *
+ * Use:                Initializes a hash function correctly for you to hash a
+ *             message.  Requires @h@.
+ */
+
+extern ghash *gdsa_beginhash(const gdsa */*c*/);
+
+/* --- @gdsa_endhash@ --- *
+ *
+ * Arguments:  @const gdsa *c@ = pointer to the context structure
+ *             @ghash *h@ = the hashing context
+ *
+ * Returns:    ---
+ *
+ * Use:                Does any final thing that DSA wants to do when hashing a
+ *             message.  (Actually, there's nothing.)  The hashing context
+ *             isn't finalized.
+ */
+
+extern void gdsa_endhash(gdsa */*c*/, ghash */*h*/);
+
+/* --- @gdsa_sign@ --- *
+ *
+ * Arguments:  @const gdsa *c@ = my context structure
+ *             @gdsa_sig *s@ = where to put the signature (initialized)
+ *             @const void *m@ = pointer to message hash
+ *             @mp *k@ = random exponent for this message or null
+ *
+ * Returns:    ---
+ *
+ * Use:                Signs a message.  Requires @g@, @u@, @h@, and @r@ if @k@ is
+ *             null.  This is a better idea than inventing @k@ yourself.
+ */
+
+extern void gdsa_sign(const gdsa */*c*/, gdsa_sig */*s*/,
+                     const void */*m*/, mp */*k*/);
+
+/* --- @gdsa_verify@ --- *
+ *
+ * Arguments:  @const gdsa *c@ = my context structure
+ *             @const gdsa_sig *s@ = the signature to verify
+ *             @const void *m@ = pointer to message hash
+ *
+ * Returns:    Zero if OK, negative on failure.
+ *
+ * Use:                Checks a signature on a message,  Requires @g@, @p@, @h@.
+ */
+
+extern int gdsa_verify(const gdsa */*c*/, const gdsa_sig */*s*/,
+                      const void */*m*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
index e08e710..76b82a6 100755 (executable)
--- a/genmodes
+++ b/genmodes
@@ -1,5 +1,6 @@
 #! /bin/sh
 
+set -e
 baselist=$1
 extlist=$2
 
index 9065f5b..da4063d 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: ghash-def.h,v 1.5 2001/01/25 21:39:58 mdw Exp $
+ * $Id: ghash-def.h,v 1.6 2004/04/04 19:42:59 mdw Exp $
  *
  * Definitions for generic hash interface
  *
@@ -30,6 +30,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: ghash-def.h,v $
+ * Revision 1.6  2004/04/04 19:42:59  mdw
+ * Add set -e.
+ *
  * Revision 1.5  2001/01/25 21:39:58  mdw
  * Burn the hash context when it's done with, for paranoia's sake.
  *
@@ -134,7 +137,7 @@ static ghash *ghcopy(ghash *h)                                              \
                                                                        \
 static const ghash_ops gops =                                          \
   { &pre, ghhash, ghdone, ghdestroy, ghcopy };                         \
-const gchash pre = { #pre, PRE##_HASHSZ, ghinit };
+const gchash pre = { #pre, PRE##_HASHSZ, ghinit, PRE##_BUFSZ };
 
 /*----- That's all, folks -------------------------------------------------*/
 
diff --git a/gkcdsa.c b/gkcdsa.c
new file mode 100644 (file)
index 0000000..f7119f5
--- /dev/null
+++ b/gkcdsa.c
@@ -0,0 +1,320 @@
+/* -*-c-*-
+ *
+ * $Id: gkcdsa.c,v 1.1 2004/04/04 19:42:59 mdw Exp $
+ *
+ * Generalized version of KCDSA
+ *
+ * (c) 2004 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------* 
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb 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.
+ * 
+ * Catacomb 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 Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: gkcdsa.c,v $
+ * Revision 1.1  2004/04/04 19:42:59  mdw
+ * Add set -e.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "gkcdsa.h"
+#include "group.h"
+#include "ghash.h"
+#include "mpbarrett.h"
+#include "mprand.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @gdsa_beginhash@ --- *
+ *
+ * Arguments:  @const gdsa *c@ = pointer to the context structure
+ *
+ * Returns:    A hashing context for you to hash the message.
+ *
+ * Use:                Initializes a hash function correctly for you to hash a
+ *             message.  Requires @h@, @g@ and @p@.
+ */
+
+ghash *gkcdsa_beginhash(const gkcdsa *c)
+{
+  ghash *h = GH_INIT(c->h);
+  mp *v = G_TOINT(c->g, MP_NEW, c->p);
+  size_t sz = c->h->bufsz;
+  void *p = xmalloc(sz);
+
+  if (/*ouch*/ !v) memset(p, 0, sz);
+  else mp_storeb(v, p, sz);
+  GH_HASH(h, p, sz);
+  mp_drop(v); xfree(p);
+  return (h);
+}
+
+/* --- @gkcdsa_endhash@ --- *
+ *
+ * Arguments:  @const gkcdsa *c@ = pointer to the context structure
+ *             @ghash *h@ = the hashing context
+ *
+ * Returns:    ---
+ *
+ * Use:                Does any final thing that KCDSA wants to do when hashing a
+ *             message.  (Actually, there's nothing.)  The hashing context
+ *             isn't finalized.
+ */
+
+void gkcdsa_endhash(gkcdsa *c, ghash *h) { ; }
+
+/* --- @hashge@ --- *
+ *
+ * Arguments:  @group *g@ = abstract group
+ *             @const gchash *hc@ = hash class
+ *             @ge *w@ = a group element
+ *
+ * Returns:    A hash context, with the hash of @w@ in it.
+ */
+
+static ghash *hashge(group *g, const gchash *hc, ge *w)
+{
+  ghash *h;
+  size_t sz;
+  void *p;
+  buf b;
+  int rc;
+
+  sz = hc->hashsz;
+  if (sz < g->noctets)
+    sz = g->noctets;
+  p = xmalloc(sz);
+  buf_init(&b, p, sz);
+  rc = G_TORAW(g, &b, w);
+  assert(rc == 0);
+  h = GH_INIT(hc);
+  GH_HASH(h, BBASE(&b), BLEN(&b));
+  xfree(p);
+  return (h);
+}
+
+/* --- @gkcdsa_sign@ --- *
+ *
+ * Arguments:  @const gkcdsa *c@ = my context structure
+ *             @gkcdsa_sig *s@ = where to put the signature (initialized)
+ *             @const void *m@ = pointer to message hash
+ *             @mp *k@ = random exponent for this message or null
+ *
+ * Returns:    ---
+ *
+ * Use:                Signs a message.  Requires @g@, @u@, @h@, and @r@ if @k@ is
+ *             null.  This is a better idea than inventing @k@ yourself.
+ */
+
+void gkcdsa_sign(const gkcdsa *c, gkcdsa_sig *s, const void *m, mp *k)
+{
+  group *g = c->g;
+  mp *x, *y;
+  ge *z = G_CREATE(g);
+  size_t hsz = c->h->hashsz;
+  ghash *h;
+
+  if (k) { MP_COPY(k); goto have_k; }
+new_k:
+  k = mprand_range(k, g->r, c->r, 0);
+have_k:
+  if (MP_ISZERO(k)) goto new_k;
+  G_EXP(g, z, g->g, k);
+  if (!s->r) s->r = xmalloc(hsz);
+  h = hashge(g, c->h, z); GH_DONE(h, s->r);
+
+  x = mp_loadb(s->s, m, hsz);
+  y = mp_loadb(MP_NEW, s->r, hsz);
+  x = mp_xor(x, x, y);
+  mp_div(0, &x, x, g->r);
+  x = mp_sub(x, g->r, x);
+  x = mp_add(x, x, k);
+  if (MP_CMP(x, >=, g->r)) x = mp_sub(x, x, g->r);
+  x = mp_mul(x, x, c->u); mp_div(0, &x, x, g->r);
+  s->s = x;
+  mp_drop(k); mp_drop(y); GH_DESTROY(h); G_DESTROY(g, z);
+}
+
+/* --- @gkcdsa_verify@ --- *
+ *
+ * Arguments:  @const gkcdsa *c@ = my context structure
+ *             @const gkcdsa_sig *s@ = the signature to verify
+ *             @const void *m@ = pointer to message hash
+ *
+ * Returns:    Zero if OK, negative on failure.
+ *
+ * Use:                Checks a signature on a message,  Requires @g@, @p@, @h@.
+ */
+
+int gkcdsa_verify(const gkcdsa *c, const gkcdsa_sig *s, const void *m)
+{
+  group *g = c->g;
+  size_t hsz = c->h->hashsz;
+  group_expfactor e[2];
+  mp *x, *y;
+  ghash *h;
+  ge *z;
+  octet *p;
+  int rc = -1;
+
+  if (MP_CMP(s->s, <, MP_ONE) || MP_CMP(s->s, >=, g->r))
+    return (-1);
+  x = mp_loadb(MP_NEW, m, hsz); y = mp_loadb(MP_NEW, s->r, hsz);
+  x = mp_xor(x, x, y); mp_div(0, &x, x, g->r);
+  e[0].base = c->p; e[0].exp = s->s;
+  e[1].base = g->g; e[1].exp = x;
+  z = G_CREATE(g); G_MEXP(g, z, e, 2);
+  h = hashge(g, c->h, z); p = GH_DONE(h, 0);
+  if (memcmp(p, s->r, hsz) == 0) rc = 0;
+  mp_drop(x); mp_drop(y); G_DESTROY(g, z); GH_DESTROY(h);
+  return (rc);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+static group *getgroup(const char *p) {
+  group *g; qd_parse qd;
+  qd.p = p; qd.e = 0; g = group_parse(&qd);
+  if (g && !qd_eofp(&qd)) { G_DESTROYGROUP(g); g = 0; qd.e = "junk at eof"; }
+  if (!g) { fprintf(stderr, "bad group string `%.*s|%s': %s\n", qd.p - p,
+                   p, qd.p, qd.e); exit(1); }
+  return (g);
+}
+
+static ge *getge(group *g, const char *p) {
+  ge *x = G_CREATE(g);
+  if (group_readstring(g, x, p, 0)) {
+    fprintf(stderr, "bad group element `%s'\n", p);
+    exit(1);
+  }
+  return (x);
+}
+
+static void showge(group *g, const char *p, ge *x) {
+  fprintf(stderr, "*** %s = ", p); group_writefile(g, x, stderr);
+  putc('\n', stderr);
+}
+
+static void showmp(const char *p, mp *x, int r) {
+  fprintf(stderr, "*** %s = ", p); mp_writefile(x, stderr, r); 
+  putc('\n', stderr);
+}
+
+static int tsign(dstr *v)
+{
+  gdsa c;
+  gkcdsa_sig s, ss = GKCDSA_SIG_INIT;
+  ghash *h;
+  mp *k;
+  dstr d = DSTR_INIT;
+  mp *x;
+  int ok = 1;
+
+  c.g = getgroup(v[0].buf); c.h = ghash_byname(v[1].buf);
+  c.u = *(mp **)v[2].buf; k = *(mp **)v[4].buf;
+  s.r = (octet *)v[5].buf; s.s = *(mp **)v[6].buf;
+  DENSURE(&d, c.h->hashsz); d.len = c.h->hashsz; memset(d.buf, 0, d.len);
+  ss.r = (octet *)d.buf;
+
+  x = MP_NEW; mp_gcd(0, 0, &x, c.g->r, c.u);
+  c.p = G_CREATE(c.g); G_EXP(c.g, c.p, c.g->g, x);
+  h = gkcdsa_beginhash(&c);
+  GH_HASH(h, v[3].buf, v[3].len);
+  gkcdsa_endhash(&c, h);
+  gkcdsa_sign(&c, &ss, GH_DONE(h, 0), k);
+  if (memcmp(s.r, ss.r, c.h->hashsz) || !MP_EQ(s.s, ss.s)) {
+    ok = 0;
+    fprintf(stderr, "*** sign failed!\n");
+    fprintf(stderr, "*** group: %s\n", v[0].buf);
+    fprintf(stderr, "*** hash: %s\n", c.h->name);
+    showmp("private key", c.u, 16);
+    showge(c.g, "public key", c.p);
+    fprintf(stderr, "*** message: `%s'\n", v[3].buf);
+    fprintf(stderr, "*** computed r = ");
+    type_hex.dump(&d, stderr); putc('\n', stderr);
+    showmp("computed s", ss.s, 16);
+    fprintf(stderr, "*** computed r = ");
+    type_hex.dump(&v[5], stderr); putc('\n', stderr);
+    showmp("expected s", s.s, 16);
+  }
+  mp_drop(s.s); dstr_destroy(&d); mp_drop(ss.s); mp_drop(x); mp_drop(k);
+  mp_drop(c.u); G_DESTROY(c.g, c.p); G_DESTROYGROUP(c.g); GH_DESTROY(h);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static int tverify(dstr *v)
+{
+  gkcdsa c;
+  gkcdsa_sig s;
+  ghash *h;
+  int rc, erc;
+  int ok = 1;
+
+  c.g = getgroup(v[0].buf); c.h = ghash_byname(v[1].buf);
+  c.p = getge(c.g, v[2].buf);
+  s.r = (octet *)v[4].buf; s.s = *(mp **)v[5].buf;
+  erc = *(int *)v[6].buf;
+
+  h = gkcdsa_beginhash(&c);
+  GH_HASH(h, v[3].buf, v[3].len);
+  gkcdsa_endhash(&c, h);
+  rc = gkcdsa_verify(&c, &s, GH_DONE(h, 0));
+  if (!rc != !erc) {
+    ok = 0;
+    fprintf(stderr, "*** verify failed!\n");
+    fprintf(stderr, "*** group: %s\n", v[0].buf);
+    fprintf(stderr, "*** hash: %s\n", c.h->name);
+    showge(c.g, "public key", c.p);
+    fprintf(stderr, "*** message: `%s'\n", v[3].buf);
+    fprintf(stderr, "*** sig r = ");
+    type_hex.dump(&v[4], stderr); putc('\n', stderr);
+    showmp("sig s", s.s, 16);
+    fprintf(stderr, "*** expected %s\n", !erc ? "pass" : "fail");
+  }
+  mp_drop(s.s); G_DESTROY(c.g, c.p); G_DESTROYGROUP(c.g);
+  GH_DESTROY(h);
+  assert(mparena_count(MPARENA_GLOBAL) == 0);
+  return (ok);
+}
+
+static const test_chunk tests[] = {
+  { "sign", tsign, { &type_string, &type_string, &type_mp, &type_string,
+                    &type_mp, &type_hex, &type_mp } },
+  { "verify", tverify, { &type_string, &type_string, &type_string,
+                        &type_string, &type_hex, &type_mp, &type_int } },
+  { 0 }
+};
+
+int main(int argc, char *argv[])
+{
+  sub_init();
+  test_run(argc, argv, tests, SRCDIR "/tests/gkcdsa");
+  return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/gkcdsa.h b/gkcdsa.h
new file mode 100644 (file)
index 0000000..8901b87
--- /dev/null
+++ b/gkcdsa.h
@@ -0,0 +1,140 @@
+/* -*-c-*-
+ *
+ * $Id: gkcdsa.h,v 1.1 2004/04/04 19:42:59 mdw Exp $
+ *
+ * Generalized version of KCDSA
+ *
+ * (c) 2004 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------* 
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb 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.
+ * 
+ * Catacomb 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 Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: gkcdsa.h,v $
+ * Revision 1.1  2004/04/04 19:42:59  mdw
+ * Add set -e.
+ *
+ */
+
+#ifndef CATACOMB_GKCDSA_H
+#define CATACOMB_GKCDSA_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_GROUP_H
+#  include "group.h"
+#endif
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+#ifndef CATACOMB_GDSA_H
+#  include "gdsa.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+/* --- Careful! --- *
+ *
+ * These structures are the same as for DSA.  However, the private key @u@ is
+ * the %$\emph{inverse}$% of the exponent.  Do this wrong and the maths will
+ * fail hopelessly.
+ */
+
+typedef gdsa gkcdsa;
+
+typedef struct gkcdsa_sig {
+  octet *r;                            /* Null means @xmalloc@ me */
+  mp *s;
+} gkcdsa_sig;
+#define GKCDSA_SIG_INIT { 0, 0 }
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @gdsa_beginhash@ --- *
+ *
+ * Arguments:  @const gdsa *c@ = pointer to the context structure
+ *
+ * Returns:    A hashing context for you to hash the message.
+ *
+ * Use:                Initializes a hash function correctly for you to hash a
+ *             message.  Requires @h@, @g@ and @p@.
+ */
+
+extern ghash *gkcdsa_beginhash(const gkcdsa */*c*/);
+
+/* --- @gkcdsa_endhash@ --- *
+ *
+ * Arguments:  @const gkcdsa *c@ = pointer to the context structure
+ *             @ghash *h@ = the hashing context
+ *
+ * Returns:    ---
+ *
+ * Use:                Does any final thing that KCDSA wants to do when hashing a
+ *             message.  (Actually, there's nothing.)  The hashing context
+ *             isn't finalized.
+ */
+
+extern void gkcdsa_endhash(gkcdsa */*c*/, ghash */*h*/);
+
+/* --- @gkcdsa_sign@ --- *
+ *
+ * Arguments:  @const gkcdsa *c@ = my context structure
+ *             @gkcdsa_sig *s@ = where to put the signature (initialized)
+ *             @const void *m@ = pointer to message hash
+ *             @mp *k@ = random exponent for this message or null
+ *
+ * Returns:    ---
+ *
+ * Use:                Signs a message.  Requires @g@, @u@, @h@, and @r@ if @k@ is
+ *             null.  This is a better idea than inventing @k@ yourself.
+ */
+
+extern void gkcdsa_sign(const gkcdsa */*c*/, gkcdsa_sig */*s*/,
+                       const void */*m*/, mp */*k*/);
+
+/* --- @gkcdsa_verify@ --- *
+ *
+ * Arguments:  @const gkcdsa *c@ = my context structure
+ *             @const gkcdsa_sig *s@ = the signature to verify
+ *             @const void *m@ = pointer to message hash
+ *
+ * Returns:    Zero if OK, negative on failure.
+ *
+ * Use:                Checks a signature on a message,  Requires @g@, @p@, @h@.
+ */
+
+extern int gkcdsa_verify(const gkcdsa */*c*/, const gkcdsa_sig */*s*/,
+                        const void */*m*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/has160.c b/has160.c
new file mode 100644 (file)
index 0000000..7c7b7b9
--- /dev/null
+++ b/has160.c
@@ -0,0 +1,256 @@
+/* -*-c-*-
+ *
+ * $Id: has160.c,v 1.1 2004/04/04 19:42:59 mdw Exp $
+ *
+ * The HAS160 message digest function
+ *
+ * (c) 2004 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------* 
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb 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.
+ * 
+ * Catacomb 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 Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: has160.c,v $
+ * Revision 1.1  2004/04/04 19:42:59  mdw
+ * Add set -e.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "ghash.h"
+#include "ghash-def.h"
+#include "hash.h"
+#include "has160.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @has160_compress@ --- *
+ *
+ * Arguments:  @has160_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                HAS160 compression function.
+ */
+
+void has160_compress(has160_ctx *ctx, const void *sbuf)
+{
+  uint32 a, b, c, d, e;
+  uint32 buf[16];
+
+  /* --- Fetch the chaining variables --- */
+
+  a = ctx->a;
+  b = ctx->b;
+  c = ctx->c;
+  d = ctx->d;
+  e = ctx->e;
+
+  /* --- Fetch the buffer contents --- */
+
+  {
+    int i;
+    const octet *p;
+
+    for (i = 0, p = sbuf; i < 16; i++, p += 4)
+      buf[i] = LOAD32_L(p);
+  }
+
+  /* --- Definitions for round functions --- */
+
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define G(x, y, z) ((x) ^ (y) ^ (z))
+#define H(x, y, z) ((y) ^ ((x) | ~(z)))
+
+#define FF(f, a, b, c, d, e, x, s, ss, k) do {                         \
+  e += ROL32(a, s) + f(b, c, d) + (x) + k;                             \
+  b = ROL32(b, ss);                                                    \
+} while (0)
+
+  /* --- The actual hashing --- *
+   *
+   * Hmm, this is more regular than most.  The macros are quite grim,
+   * though.
+   */
+
+#define ROUND(f, ss, k,                                                        \
+     i0,  i1,  i2,  i3,  i4,  i5,  i6,  i7,                            \
+     i8,  i9, i10, i11, i12, i13, i14, i15) do {                       \
+  FF(f, a, b, c, d, e, buf[ i8]^buf[ i9]^buf[i10]^buf[i11],  5, ss, k);        \
+  FF(f, e, a, b, c, d,                            buf[ i0], 11, ss, k);        \
+  FF(f, d, e, a, b, c,                            buf[ i1],  7, ss, k);        \
+  FF(f, c, d, e, a, b,                            buf[ i2], 15, ss, k);        \
+  FF(f, b, c, d, e, a,                            buf[ i3],  6, ss, k);        \
+  FF(f, a, b, c, d, e, buf[i12]^buf[i13]^buf[i14]^buf[i15], 13, ss, k);        \
+  FF(f, e, a, b, c, d,                            buf[ i4],  8, ss, k);        \
+  FF(f, d, e, a, b, c,                            buf[ i5], 14, ss, k);        \
+  FF(f, c, d, e, a, b,                            buf[ i6],  7, ss, k);        \
+  FF(f, b, c, d, e, a,                            buf[ i7], 12, ss, k);        \
+  FF(f, a, b, c, d, e, buf[ i0]^buf[ i1]^buf[ i2]^buf[ i3],  9, ss, k);        \
+  FF(f, e, a, b, c, d,                            buf[ i8], 11, ss, k);        \
+  FF(f, d, e, a, b, c,                            buf[ i9],  8, ss, k);        \
+  FF(f, c, d, e, a, b,                            buf[i10], 15, ss, k);        \
+  FF(f, b, c, d, e, a,                            buf[i11],  6, ss, k);        \
+  FF(f, a, b, c, d, e, buf[ i4]^buf[ i5]^buf[ i6]^buf[ i7], 12, ss, k);        \
+  FF(f, e, a, b, c, d,                            buf[i12],  9, ss, k);        \
+  FF(f, d, e, a, b, c,                            buf[i13], 14, ss, k);        \
+  FF(f, c, d, e, a, b,                            buf[i14],  5, ss, k);        \
+  FF(f, b, c, d, e, a,                            buf[i15], 13, ss, k); \
+} while (0)
+
+  ROUND(F, 10, 0x00000000,
+        0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15);
+  ROUND(G, 17, 0x5a827999,
+        3,  6,  9, 12, 15,  2,  5,  8, 11, 14,  1,  4,  7, 10, 13,  0);
+  ROUND(H, 25, 0x6ed9eba1,
+       12,  5, 14,  7,  0,  9,  2, 11,  4, 13,  6, 15,  8,  1, 10,  3);
+  ROUND(G, 30, 0x8f1bbcdc,
+        7,  2, 13,  8,  3, 14,  9,  4, 15, 10,  5,  0, 11,  6,  1, 12);
+
+  /* --- Update the chaining variables --- */
+
+  ctx->a += a;
+  ctx->b += b;
+  ctx->c += c;
+  ctx->d += d;
+  ctx->e += e;
+}
+
+/* --- @has160_init@ --- *
+ *
+ * Arguments:  @has160_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+void has160_init(has160_ctx *ctx)
+{
+  ctx->a = 0x67452301;
+  ctx->b = 0xefcdab89;
+  ctx->c = 0x98badcfe;
+  ctx->d = 0x10325476;
+  ctx->e = 0xc3d2e1f0;
+  ctx->off = 0;
+  ctx->nl = ctx->nh = 0;
+}
+
+/* --- @has160_set@ --- *
+ *
+ * Arguments:  @has160_ctx *ctx@ = pointer to context block
+ *             @const void *buf@ = pointer to state buffer
+ *             @unsigned long count@ = current count of bytes processed
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block from a given state.  This is
+ *             useful in cases where the initial hash state is meant to be
+ *             secret, e.g., for NMAC and HMAC support.
+ */
+
+void has160_set(has160_ctx *ctx, const void *buf, unsigned long count)
+{
+  const octet *p = buf;
+  ctx->a = LOAD32_L(p +  0);
+  ctx->b = LOAD32_L(p +  4);
+  ctx->c = LOAD32_L(p +  8);
+  ctx->d = LOAD32_L(p + 12);
+  ctx->e = LOAD32_L(p + 16);
+  ctx->off = 0;
+  ctx->nl = U32(count);
+  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
+}
+
+/* --- @has160_hash@ --- *
+ *
+ * Arguments:  @has160_ctx *ctx@ = pointer to context block
+ *             @const void *buf@ = buffer of data to hash
+ *             @size_t sz@ = size of buffer to hash
+ *
+ * Returns:    ---
+ *
+ * Use:                Hashes a buffer of data.  The buffer may be of any size and
+ *             alignment.
+ */
+
+void has160_hash(has160_ctx *ctx, const void *buf, size_t sz)
+{
+  HASH_BUFFER(HAS160, has160, ctx, buf, sz);
+}
+
+/* --- @has160_done@ --- *
+ *
+ * Arguments:  @has160_ctx *ctx@ = pointer to context block
+ *             @void *hash@ = pointer to output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Returns the hash of the data read so far.
+ */
+
+void has160_done(has160_ctx *ctx, void *hash)
+{
+  octet *p = hash;
+  HASH_MD5STRENGTH(HAS160, has160, ctx);
+  STORE32_L(p +  0, ctx->a);
+  STORE32_L(p +  4, ctx->b);
+  STORE32_L(p +  8, ctx->c);
+  STORE32_L(p + 12, ctx->d);
+  STORE32_L(p + 16, ctx->e);
+}
+
+/* --- @has160_state@ --- *
+ *
+ * Arguments:  @has160_ctx *ctx@ = pointer to context
+ *             @void *state@ = pointer to buffer for current state
+ *
+ * Returns:    Number of bytes written to the hash function so far.
+ *
+ * Use:                Returns the current state of the hash function such that
+ *             it can be passed to @has160_set@.
+ */
+
+unsigned long has160_state(has160_ctx *ctx, void *state)
+{
+  octet *p = state;
+  STORE32_L(p +  0, ctx->a);
+  STORE32_L(p +  4, ctx->b);
+  STORE32_L(p +  8, ctx->c);
+  STORE32_L(p + 12, ctx->d);
+  STORE32_L(p + 16, ctx->e);
+  return (ctx->nl | ((ctx->nh << 16) << 16));
+}
+
+/* --- Generic interface --- */
+
+GHASH_DEF(HAS160, has160)
+
+/* --- Test code --- */
+
+HASH_TEST(HAS160, has160)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/has160.h b/has160.h
new file mode 100644 (file)
index 0000000..f60fdc9
--- /dev/null
+++ b/has160.h
@@ -0,0 +1,167 @@
+/* -*-c-*-
+ *
+ * $Id: has160.h,v 1.1 2004/04/04 19:42:59 mdw Exp $
+ *
+ * The HAS160 message digest function
+ *
+ * (c) 2004 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------* 
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb 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.
+ * 
+ * Catacomb 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 Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: has160.h,v $
+ * Revision 1.1  2004/04/04 19:42:59  mdw
+ * Add set -e.
+ *
+ */
+
+/*----- Notes on the HAS160 hash function ---------------------------------*
+ *
+ * HAS160 was designed by Chae Hoon Lim and the Korean Information Security
+ * Agency (KISA).  It's recommended for use with KCDSA (though I think I'm
+ * happer with RIPEMD-160 or SHA1).  It's here so I can check KCDSA test
+ * vectors.
+ */
+
+#ifndef CATACOMB_HAS160_H
+#define CATACOMB_HAS160_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define HAS160_BUFSZ 64
+#define HAS160_HASHSZ 20
+#define HAS160_STATESZ 20
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct has160_ctx {
+  uint32 a, b, c, d, e;                        /* Chaining variables */
+  uint32 nl, nh;                       /* Byte count so far */
+  unsigned off;                                /* Offset into buffer */
+  octet buf[HAS160_BUFSZ];             /* Accumulation buffer */
+} has160_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @has160_compress@ --- *
+ *
+ * Arguments:  @has160_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                HAS160 compression function.
+ */
+
+extern void has160_compress(has160_ctx */*ctx*/, const void */*sbuf*/);
+
+/* --- @has160_init@ --- *
+ *
+ * Arguments:  @has160_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+extern void has160_init(has160_ctx */*ctx*/);
+
+/* --- @has160_set@ --- *
+ *
+ * Arguments:  @has160_ctx *ctx@ = pointer to context block
+ *             @const void *buf@ = pointer to state buffer
+ *             @unsigned long count@ = current count of bytes processed
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block from a given state.  This is
+ *             useful in cases where the initial hash state is meant to be
+ *             secret, e.g., for NMAC and HMAC support.
+ */
+
+extern void has160_set(has160_ctx */*ctx*/, const void */*buf*/,
+                      unsigned long /*count*/);
+
+/* --- @has160_hash@ --- *
+ *
+ * Arguments:  @has160_ctx *ctx@ = pointer to context block
+ *             @const void *buf@ = buffer of data to hash
+ *             @size_t sz@ = size of buffer to hash
+ *
+ * Returns:    ---
+ *
+ * Use:                Hashes a buffer of data.  The buffer may be of any size and
+ *             alignment.
+ */
+
+extern void has160_hash(has160_ctx */*ctx*/,
+                       const void */*buf*/, size_t /*sz*/);
+
+/* --- @has160_done@ --- *
+ *
+ * Arguments:  @has160_ctx *ctx@ = pointer to context block
+ *             @void *hash@ = pointer to output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Returns the hash of the data read so far.
+ */
+
+extern void has160_done(has160_ctx */*ctx*/, void */*hash*/);
+
+/* --- @has160_state@ --- *
+ *
+ * Arguments:  @has160_ctx *ctx@ = pointer to context
+ *             @void *state@ = pointer to buffer for current state
+ *
+ * Returns:    Number of bytes written to the hash function so far.
+ *
+ * Use:                Returns the current state of the hash function such that
+ *             it can be passed to @has160_set@.
+ */
+
+extern unsigned long has160_state(has160_ctx */*ctx*/, void */*state*/);
+
+/*----- Generic hash interface --------------------------------------------*/
+
+extern const gchash has160;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
index f2ced4b..11a5d37 100644 (file)
--- a/hashsum.c
+++ b/hashsum.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: hashsum.c,v 1.8 2001/04/19 18:26:33 mdw Exp $
+ * $Id: hashsum.c,v 1.9 2004/04/04 19:42:59 mdw Exp $
  *
  * Hash files using some secure hash function
  *
@@ -30,6 +30,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: hashsum.c,v $
+ * Revision 1.9  2004/04/04 19:42:59  mdw
+ * Add set -e.
+ *
  * Revision 1.8  2001/04/19 18:26:33  mdw
  * Add CRC as another hash function.
  *
 
 #include "ghash.h"
 
-#include "crc32.h"
-#include "md2.h"
-#include "md4.h"
-#include "md5.h"
-#include "rmd128.h"
-#include "rmd160.h"
-#include "rmd256.h"
-#include "rmd320.h"
-#include "sha.h"
-#include "sha256.h"
-#include "sha384.h"
-#include "sha512.h"
-#include "tiger.h"
-
 /*----- Static variables --------------------------------------------------*/
 
-static const gchash *hashtab[] = {
-  &md5, &md4, &md2,
-  &sha, &sha256, &sha384, &sha512,
-  &rmd128, &rmd160, &rmd256, &rmd320,
-  &tiger, &gcrc32,
-  0
-};
-
 #define f_binary 1u
 #define f_bogus 2u
 #define f_verbose 4u
@@ -212,9 +193,9 @@ static size_t gethex(const char *p, octet *q, size_t sz, char **pp)
 
 static const gchash *gethash(const char *name)
 {
-  const gchash **g, *gg = 0;
+  const gchash *const *g, *gg = 0;
   size_t sz = strlen(name);
-  for (g = hashtab; *g; g++) {
+  for (g = ghashtab; *g; g++) {
     if (strncmp(name, (*g)->name, sz) == 0) {
       if ((*g)->name[sz] == 0) {
        gg = *g;
@@ -618,7 +599,7 @@ int main(int argc, char *argv[])
       gch = gethash(q);
     }
     if (!gch)
-      gch = hashtab[0];
+      gch = gethash("md5");
     xfree(q);
   }
 
@@ -666,10 +647,10 @@ int main(int argc, char *argv[])
        break;
       case 'l': {
        unsigned j;
-       for (j = 0; hashtab[j]; j++) {
+       for (j = 0; ghashtab[j]; j++) {
          if (j)
            fputc(' ', stdout);
-         printf("%s", hashtab[j]->name);
+         printf("%s", ghashtab[j]->name);
        }
        fputc('\n', stdout);
        exit(0);
diff --git a/tests/gdsa b/tests/gdsa
new file mode 100644 (file)
index 0000000..60a9f6f
--- /dev/null
@@ -0,0 +1,160 @@
+# $Id: gdsa,v 1.1 2004/04/04 19:42:59 mdw Exp $
+#
+# Tests for abstract-group implementation of DSA
+
+sign {
+  # --- A simple and small test ---
+
+  "prime {
+    0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5,
+    0x84d192cd06ae59691897fa409da6198d5269325d,
+    0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e
+  }"
+  sha
+  0x1234
+  "An example message"
+  0x649b1058e0fe7ee849d3cb00b8ec3053ad0793b8
+  0x2718bf488b981992b164e664224dd00ca1ed4e1c
+  0x5c085679fbfa9ee806781bdbd86a67dbf14df640;
+
+  # --- The FIPS186-1 test vector ---
+
+  "prime {
+    0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291,
+    0xc773218c737ec8ee993b4f2ded30f48edace915f,
+    0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802
+  }"
+  sha
+  0x2070b3223dba372fde1c0ffc7b2e3b498b260614
+  "abc"
+  0x358dad571462710f50e254cf1a376b2bdeaadfbf
+  0x8bac1ab66410435cb7181f95b16ab97c92b341c0
+  0x41e2345f1f56df2458f426d155b4ba2db6dcd8c8;
+
+  # --- A test I made up ---
+
+  "prime {
+    0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7,
+    0xfd367bd179b5425ef9bb1f51d7d9a916e58288f9,
+    0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014
+  }"
+  sha
+  0x23a252f60bae4907a8ed5b6203e2b1da32848cd9
+  "A message signed with a 1024-bit DSA key."
+  0x12ccb231683a3d9c13dca6fe882349537eebfd03
+  0x2a301061ac185440fbf595f8f7d894158b8d1897
+  0x51aedaa73cb8d47e07281d14dda5ea8c0ddf7503;
+
+  # --- Elliptic curve test vectors ---
+
+  "ec { nist-b163 }" sha 0x1234
+  "An example message"
+  0x649b1058e0fe7ee849d3cb00b8ec3053ad0793b8
+  0x12e2f4e865bf6e034712b4f2ba6f3c825452d6419
+  0x30e0d918fde3a33781f984b877f8501356b6fbae9;
+
+  "ec { nist-p256 }" sha256
+  0x7fb838a8a0a95046b9d9d9fb4440f7bbc1a7bd3b4e853fc92d4e1588719986aa
+  "An example message"
+  0x8d68905434b020ccb849e17a03a5c441d2a104aaf523699c1cc7a93174d21d9c
+  0xb30f954bfb624041e56f09ece884c17c74f866c24149bba0712303a9530142a6
+  0x1076bd32f298aaffa8c6242d881d928b1c4e0f5ad7e8ce3c4d815fe348a9666a;
+}
+
+verify {
+  # --- A simple and small test ---
+
+  "prime {
+    0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5,
+    0x84d192cd06ae59691897fa409da6198d5269325d,
+    0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e
+  }"
+  sha
+  0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47
+  "An example message"
+  0x2718bf488b981992b164e664224dd00ca1ed4e1c
+  0x5c085679fbfa9ee806781bdbd86a67dbf14df640
+  0;
+
+  "prime {
+    0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5,
+    0x84d192cd06ae59691897fa409da6198d5269325d,
+    0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e
+  }"
+  sha
+  0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47
+  "An example messag"
+  0x2718bf488b981992b164e664224dd00ca1ed4e1c
+  0x5c085679fbfa9ee806781bdbd86a67dbf14df640
+  -1;
+
+  "prime {
+    0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5,
+    0x84d192cd06ae59691897fa409da6198d5269325d,
+    0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e
+  }"
+  sha
+  0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47
+  "An example message"
+  0x2718bf488b981992b164e664224dd00ca1ed4e1c
+  0x5c085679fbfa9ee806781bdbd86a67dbf14df641
+  -1;
+
+  "prime {
+    0xc9c7feaeaedb16505389c5582df1858d0fdb3eecfe61c230d612661bef8c1bc5,
+    0x84d192cd06ae59691897fa409da6198d5269325d,
+    0x5cd41fc97d0db5322bab7d659354db2ed9f88e39d2c6fae9f29acab5a522131e
+  }"
+  sha
+  0x51812af9600c89ffe0f73902eb09015c03b4e0fbf6ccf073931c12f9aad1fb47
+  "An example message"
+  0x2718bf488b981992b164e664224dd00ca1ed4e1c
+  0xe0d9e94702a8f8511f10161c7610816943b7289d
+  -1;
+
+  # --- The FIPS186-1 test vector ---
+
+  "prime {
+    0x8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291,
+    0xc773218c737ec8ee993b4f2ded30f48edace915f,
+    0x626d027839ea0a13413163a55b4cb500299d5522956cefcb3bff10f399ce2c2e71cb9de5fa24babf58e5b79521925c9cc42e9f6f464b088cc572af53e6d78802
+  }"
+  sha
+  0x19131871d75b1612a819f29d78d1b0d7346f7aa77bb62a859bfd6c5675da9d212d3a36ef1672ef660b8c7c255cc0ec74858fba33f44c06699630a76b030ee333
+  "abc"
+  0x8bac1ab66410435cb7181f95b16ab97c92b341c0
+  0x41e2345f1f56df2458f426d155b4ba2db6dcd8c8 
+  0;
+
+  # --- A test I made up ---
+
+  "prime {
+    0xdde5808744e1cd37c88667e7033694b2513a7429f035f11c0bafc4dff2b96a672bd0a3ca16aba2ea526df00c8571106ba4a1d83eb62605fc9274ab70bef0a111cd070cca2d8b10edf042d6c44f863c36fabea8bb0d7340eb8c169da27a4b0ba2713c166152a0244235093391c5f71aee8c03dcaf2335a2e4689ccb27ba365ec7,
+    0xfd367bd179b5425ef9bb1f51d7d9a916e58288f9,
+    0x65985e4c2d6027a8afdeb9b44cc619e1c4d46bde873e0d4b45325412a2f8365e51245324f888704295fe8233a6666624d9a4701172dbfcab5c9643e1caab79eb2a0c85284d1b858688b8f16804326321f53a723502a6d6ae08dcbffccf2187a799f6281c2478ef0faed5c5c80adeabc5ee435cff8b9ae0b603e47fb08d73b014
+  }"
+  sha
+  0x9720498d8ec1208585635faaf952c1204c37119acccc64ed7942867be24770e33db39ffcfa1194549ead8495a7918a20e15144e68125860ef4f8c1a3d771bad690938bdb2c8817e2b89a8fc615d067084a7a2f2f9280e15fb9ccebfe713584260d5ed30545b69745d7b22977bfd44d60d7c5e657aab1c79dc5cb33ff29ee9074
+  "A message signed with a 1024-bit DSA key."
+  0x2a301061ac185440fbf595f8f7d894158b8d1897
+  0x51aedaa73cb8d47e07281d14dda5ea8c0ddf7503
+  0;
+
+  # --- Elliptic curve test vectors ---
+
+  "ec { nist-b163 }" sha
+  "0x1e7d847d0331a794852ded2b96c71d82e61f9bb4c, 
+    0x1a2370ab2e63f5aa8f348fbe83c0415a7d8ee207b"
+  "An example message"
+  0x12e2f4e865bf6e034712b4f2ba6f3c825452d6419
+  0x30e0d918fde3a33781f984b877f8501356b6fbae9
+  0;
+
+  "ec { nist-p256 }" sha256
+  "0xcc2aecbc5c5f6d72cd7b937279d72a732abcf880ea47e012ebec77ddbca6ed40,
+    0x90f99cd799abc0ea571d0e02bad80f8323050b1adbdbff50060b6e1e6ebd8611"
+  "An example message"
+  0xb30f954bfb624041e56f09ece884c17c74f866c24149bba0712303a9530142a6
+  0x1076bd32f298aaffa8c6242d881d928b1c4e0f5ad7e8ce3c4d815fe348a9666a 
+  0;
+}
diff --git a/tests/gkcdsa b/tests/gkcdsa
new file mode 100644 (file)
index 0000000..214947b
--- /dev/null
@@ -0,0 +1,59 @@
+# $Id: gkcdsa,v 1.1 2004/04/04 19:42:59 mdw Exp $
+#
+# Tests for KCDSA
+
+sign {
+  "prime {
+    0xd7b9afc104f4d53f737db88d6bf77e12cd7ec3d71cbe3cb74cd224bff348154afba6bfed797044dfc655dcc20c952c0ec43a97e1ad67e687d10729caf622845d162afca8f0248cc412b3596c4c5d3384f7e25ee644ba87bb09b164fb465477b87fdba5eaa400ffa0925714ae19464ffacead3a9750d121948ab2d8d65c82379f,
+    0xc3ddd3717bf05b8f8dd725c162f0b9432c6f77fb,
+    0x50e414c7a56892d1ad633e42d5cd8346f2c09808111c772cc30b0c544102c27e7b5f9bec57b9df2a153128919d795e46652b2a072e1f2517f2a3afff5815253aaefe35724cfa1af6afce3a6b41e3d0e13bed0eff54383c4665e69b47ba79bbc3339f86b9be2b58894a18b201afc41fe3a0d93d3125efda79bc50dbbb2c3ab639
+  }"
+  has160
+  0x068c4ef355d8b6f53eff1df6f243f98563896c58
+  "This is a test message for KCDSA usage!"
+  0x4b037e4b573bb7e334cad0a70bed6b5881df9e8e
+  8f996a98eda57cc8d88aa6ffdfaea22f39d7fa8a
+  0x541f7dc4f92c65eb7f63b6b4f22177f1ee2cf339;
+
+  "ec { nist-p256 }" sha256
+  0x7fb838a8a0a95046b9d9d9fb4440f7bbc1a7bd3b4e853fc92d4e1588719986aa
+  "Testing elliptic curves with KCDSA"
+  0x8d68905434b020ccb849e17a03a5c441d2a104aaf523699c1cc7a93174d21d9c
+  e3f05cea444ec44d508b3af5b8d2d8eb2bcbff680e83684e3e630ec5b07393c0
+  0x42e307f5fa0a4e01906b067965f6253f1a7919a566cf3d73ddd9a35a17b38617;
+}
+
+verify {
+  "prime {
+    0xd7b9afc104f4d53f737db88d6bf77e12cd7ec3d71cbe3cb74cd224bff348154afba6bfed797044dfc655dcc20c952c0ec43a97e1ad67e687d10729caf622845d162afca8f0248cc412b3596c4c5d3384f7e25ee644ba87bb09b164fb465477b87fdba5eaa400ffa0925714ae19464ffacead3a9750d121948ab2d8d65c82379f,
+    0xc3ddd3717bf05b8f8dd725c162f0b9432c6f77fb,
+    0x50e414c7a56892d1ad633e42d5cd8346f2c09808111c772cc30b0c544102c27e7b5f9bec57b9df2a153128919d795e46652b2a072e1f2517f2a3afff5815253aaefe35724cfa1af6afce3a6b41e3d0e13bed0eff54383c4665e69b47ba79bbc3339f86b9be2b58894a18b201afc41fe3a0d93d3125efda79bc50dbbb2c3ab639
+  }"
+  has160
+  0x96dce0e7b2f170093d9b51d2ba78202733b62c406d3769758b3e0cbba1ff6c78727a35703cb6bc2476c3c293743dfee94aa4b9efa9a17fa6bf790ac25a82c61523f50abaac7b64647eb15c957b07f5ed7d467243089f74695cd58fbf57920cc0c05d45829c0a8161b943f18451845760ed096540e78aa9750b03d02448cbf8de
+  "This is a test message for KCDSA usage!"
+  8f996a98eda57cc8d88aa6ffdfaea22f39d7fa8a
+  0x541f7dc4f92c65eb7f63b6b4f22177f1ee2cf339
+  0;
+
+  "prime {
+    0xd7b9afc104f4d53f737db88d6bf77e12cd7ec3d71cbe3cb74cd224bff348154afba6bfed797044dfc655dcc20c952c0ec43a97e1ad67e687d10729caf622845d162afca8f0248cc412b3596c4c5d3384f7e25ee644ba87bb09b164fb465477b87fdba5eaa400ffa0925714ae19464ffacead3a9750d121948ab2d8d65c82379f,
+    0xc3ddd3717bf05b8f8dd725c162f0b9432c6f77fb,
+    0x50e414c7a56892d1ad633e42d5cd8346f2c09808111c772cc30b0c544102c27e7b5f9bec57b9df2a153128919d795e46652b2a072e1f2517f2a3afff5815253aaefe35724cfa1af6afce3a6b41e3d0e13bed0eff54383c4665e69b47ba79bbc3339f86b9be2b58894a18b201afc41fe3a0d93d3125efda79bc50dbbb2c3ab639
+  }"
+  has160
+  0x96dce0e7b2f170093d9b51d2ba78202733b62c406d3769758b3e0cbba1ff6c78727a35703cb6bc2476c3c293743dfee94aa4b9efa9a17fa6bf790ac25a82c61523f50abaac7b64647eb15c957b07f5ed7d467243089f74695cd58fbf57920cc0c05d45829c0a8161b943f18451845760ed096540e78aa9750b03d02448cbf8de
+  "This is a test message for KCDSA usage?"
+  8f996a98eda57cc8d88aa6ffdfaea22f39d7fa8a
+  0x541f7dc4f92c65eb7f63b6b4f22177f1ee2cf339
+  -1;
+
+  "ec { nist-p256 }" sha256
+  "0x5068f177ccebee933a27457707f6879eb5c4c59d58483766caf9aabcc367c0d1, 
+    0x4869c59dceadad93f1ed306b3ed544356c119996cc78708b9557c7ca5901da4a"
+  "Testing elliptic curves with KCDSA"
+  e3f05cea444ec44d508b3af5b8d2d8eb2bcbff680e83684e3e630ec5b07393c0
+  0x42e307f5fa0a4e01906b067965f6253f1a7919a566cf3d73ddd9a35a17b38617
+  0;
+}
+
diff --git a/tests/has160 b/tests/has160
new file mode 100644 (file)
index 0000000..ba3db65
--- /dev/null
@@ -0,0 +1,53 @@
+# Test vectors for HAS160 hash function
+#
+# $Id: has160,v 1.1 2004/04/04 19:42:59 mdw Exp $
+
+# --- Basic hash function ---
+#
+# Test vectors from `The Revised Version of KCDSA' by Chae Hoon Lim.
+
+has160 {
+  ""                           307964ef34151d37c8047adec7ab50f4ff89762d;
+  "a"                          4872bcbc4cd0f0a9dc7c2f7045e5b43b6c830db8;
+  "abc"                                975e810488cf2a3d49838478124afce4b1c78804;
+  "message digest"             2338dbc8638d31225f73086246ba529f96710bc6;
+  "abcdefghijklmnopqrstuvwxyz" 596185c9ab6703d0d0dbb98702bc0f5729cd1d3c;
+}
+
+has160-rep {
+  "a" 1000000                  d6ad6f0608b878da9b87999c2525cc84f4c9f18d;
+}
+
+# --- HMAC mode ---
+#
+# Regression catching only.
+
+has160-hmac {
+  "Hi There"
+       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+       f5b44115a53f716b6f488de1098ee7c251418623;
+
+  "what do ya want for nothing?"
+       4a656665
+       a74547c1ef0aa147c7428ab7e71664549be2a412;
+
+  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       e4c91bc71782fa44a56be1a34aae167e8ffc9734;
+
+  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
+       0102030405060708090a0b0c0d0e0f10111213141516171819
+       14d1055da875222053bf1180bbef8892eba3ac30;
+
+  "Test With Truncation"
+       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+       124131a293f1fdf3d6b11e2b7f7a1f5b12e42d58;
+
+  "Test Using Larger Than Block-Size Key - Hash Key First"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       63750d67af40e3fde33526545d300972a1527053;
+
+  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       1bdb821e399e208352c64f0655f6601e2a8a087c;
+}