sha224-mgf.h
junk
deb-build
+has160-hmac.c
+has160-hmac.h
+has160-mgf.c
+has160-mgf.h
## -*-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
##
##----- 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.
##
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)')
$(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') \
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 \
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 \
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 \
## --- 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 \
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; \
CTESTRIG(ec-info)
CTESTRIG(dh-param)
CTESTRIG(group-test)
+CTESTRIG(gdsa)
+CTESTRIG(gkcdsa)
CTESTRIG(pgen)
CTESTRIG(dsa-gen)
CTESTRIG(dsa-sign)
/* -*-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
*
/*----- 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)
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 },
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;
--- /dev/null
+/* -*-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 -------------------------------------------------*/
--- /dev/null
+/* -*-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
#! /bin/sh
+set -e
baselist=$1
extlist=$2
/* -*-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
*
/*----- 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.
*
\
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 -------------------------------------------------*/
--- /dev/null
+/* -*-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 -------------------------------------------------*/
--- /dev/null
+/* -*-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
--- /dev/null
+/* -*-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 -------------------------------------------------*/
--- /dev/null
+/* -*-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
/* -*-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
*
/*----- 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
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;
gch = gethash(q);
}
if (!gch)
- gch = hashtab[0];
+ gch = gethash("md5");
xfree(q);
}
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);
--- /dev/null
+# $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;
+}
--- /dev/null
+# $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;
+}
+
--- /dev/null
+# 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;
+}